123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- DeclTemplate.h - Classes for representing C++ templates --*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- /// \file
- /// Defines the C++ template declaration subclasses.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_CLANG_AST_DECLTEMPLATE_H
- #define LLVM_CLANG_AST_DECLTEMPLATE_H
- #include "clang/AST/ASTConcept.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/Decl.h"
- #include "clang/AST/DeclBase.h"
- #include "clang/AST/DeclCXX.h"
- #include "clang/AST/DeclarationName.h"
- #include "clang/AST/Redeclarable.h"
- #include "clang/AST/TemplateBase.h"
- #include "clang/AST/Type.h"
- #include "clang/Basic/LLVM.h"
- #include "clang/Basic/SourceLocation.h"
- #include "clang/Basic/Specifiers.h"
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/ADT/FoldingSet.h"
- #include "llvm/ADT/PointerIntPair.h"
- #include "llvm/ADT/PointerUnion.h"
- #include "llvm/ADT/iterator.h"
- #include "llvm/ADT/iterator_range.h"
- #include "llvm/Support/Casting.h"
- #include "llvm/Support/Compiler.h"
- #include "llvm/Support/TrailingObjects.h"
- #include <cassert>
- #include <cstddef>
- #include <cstdint>
- #include <iterator>
- #include <optional>
- #include <utility>
- namespace clang {
- enum BuiltinTemplateKind : int;
- class ClassTemplateDecl;
- class ClassTemplatePartialSpecializationDecl;
- class Expr;
- class FunctionTemplateDecl;
- class IdentifierInfo;
- class NonTypeTemplateParmDecl;
- class TemplateDecl;
- class TemplateTemplateParmDecl;
- class TemplateTypeParmDecl;
- class ConceptDecl;
- class UnresolvedSetImpl;
- class VarTemplateDecl;
- class VarTemplatePartialSpecializationDecl;
- /// Stores a template parameter of any kind.
- using TemplateParameter =
- llvm::PointerUnion<TemplateTypeParmDecl *, NonTypeTemplateParmDecl *,
- TemplateTemplateParmDecl *>;
- NamedDecl *getAsNamedDecl(TemplateParameter P);
- /// Stores a list of template parameters for a TemplateDecl and its
- /// derived classes.
- class TemplateParameterList final
- : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *,
- Expr *> {
- /// The location of the 'template' keyword.
- SourceLocation TemplateLoc;
- /// The locations of the '<' and '>' angle brackets.
- SourceLocation LAngleLoc, RAngleLoc;
- /// The number of template parameters in this template
- /// parameter list.
- unsigned NumParams : 29;
- /// Whether this template parameter list contains an unexpanded parameter
- /// pack.
- unsigned ContainsUnexpandedParameterPack : 1;
- /// Whether this template parameter list has a requires clause.
- unsigned HasRequiresClause : 1;
- /// Whether any of the template parameters has constrained-parameter
- /// constraint-expression.
- unsigned HasConstrainedParameters : 1;
- protected:
- TemplateParameterList(const ASTContext& C, SourceLocation TemplateLoc,
- SourceLocation LAngleLoc, ArrayRef<NamedDecl *> Params,
- SourceLocation RAngleLoc, Expr *RequiresClause);
- size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
- return NumParams;
- }
- size_t numTrailingObjects(OverloadToken<Expr *>) const {
- return HasRequiresClause ? 1 : 0;
- }
- public:
- template <size_t N, bool HasRequiresClause>
- friend class FixedSizeTemplateParameterListStorage;
- friend TrailingObjects;
- static TemplateParameterList *Create(const ASTContext &C,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- ArrayRef<NamedDecl *> Params,
- SourceLocation RAngleLoc,
- Expr *RequiresClause);
- /// Iterates through the template parameters in this list.
- using iterator = NamedDecl **;
- /// Iterates through the template parameters in this list.
- using const_iterator = NamedDecl * const *;
- iterator begin() { return getTrailingObjects<NamedDecl *>(); }
- const_iterator begin() const { return getTrailingObjects<NamedDecl *>(); }
- iterator end() { return begin() + NumParams; }
- const_iterator end() const { return begin() + NumParams; }
- unsigned size() const { return NumParams; }
- ArrayRef<NamedDecl *> asArray() { return llvm::ArrayRef(begin(), end()); }
- ArrayRef<const NamedDecl*> asArray() const {
- return llvm::ArrayRef(begin(), size());
- }
- NamedDecl* getParam(unsigned Idx) {
- assert(Idx < size() && "Template parameter index out-of-range");
- return begin()[Idx];
- }
- const NamedDecl* getParam(unsigned Idx) const {
- assert(Idx < size() && "Template parameter index out-of-range");
- return begin()[Idx];
- }
- /// Returns the minimum number of arguments needed to form a
- /// template specialization.
- ///
- /// This may be fewer than the number of template parameters, if some of
- /// the parameters have default arguments or if there is a parameter pack.
- unsigned getMinRequiredArguments() const;
- /// Get the depth of this template parameter list in the set of
- /// template parameter lists.
- ///
- /// The first template parameter list in a declaration will have depth 0,
- /// the second template parameter list will have depth 1, etc.
- unsigned getDepth() const;
- /// Determine whether this template parameter list contains an
- /// unexpanded parameter pack.
- bool containsUnexpandedParameterPack() const;
- /// Determine whether this template parameter list contains a parameter pack.
- bool hasParameterPack() const {
- for (const NamedDecl *P : asArray())
- if (P->isParameterPack())
- return true;
- return false;
- }
- /// The constraint-expression of the associated requires-clause.
- Expr *getRequiresClause() {
- return HasRequiresClause ? getTrailingObjects<Expr *>()[0] : nullptr;
- }
- /// The constraint-expression of the associated requires-clause.
- const Expr *getRequiresClause() const {
- return HasRequiresClause ? getTrailingObjects<Expr *>()[0] : nullptr;
- }
- /// \brief All associated constraints derived from this template parameter
- /// list, including the requires clause and any constraints derived from
- /// constrained-parameters.
- ///
- /// The constraints in the resulting list are to be treated as if in a
- /// conjunction ("and").
- void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const;
- bool hasAssociatedConstraints() const;
- SourceLocation getTemplateLoc() const { return TemplateLoc; }
- SourceLocation getLAngleLoc() const { return LAngleLoc; }
- SourceLocation getRAngleLoc() const { return RAngleLoc; }
- SourceRange getSourceRange() const LLVM_READONLY {
- return SourceRange(TemplateLoc, RAngleLoc);
- }
- void print(raw_ostream &Out, const ASTContext &Context,
- bool OmitTemplateKW = false) const;
- void print(raw_ostream &Out, const ASTContext &Context,
- const PrintingPolicy &Policy, bool OmitTemplateKW = false) const;
- static bool shouldIncludeTypeForArgument(const PrintingPolicy &Policy,
- const TemplateParameterList *TPL,
- unsigned Idx);
- };
- /// Stores a list of template parameters and the associated
- /// requires-clause (if any) for a TemplateDecl and its derived classes.
- /// Suitable for creating on the stack.
- template <size_t N, bool HasRequiresClause>
- class FixedSizeTemplateParameterListStorage
- : public TemplateParameterList::FixedSizeStorageOwner {
- typename TemplateParameterList::FixedSizeStorage<
- NamedDecl *, Expr *>::with_counts<
- N, HasRequiresClause ? 1u : 0u
- >::type storage;
- public:
- FixedSizeTemplateParameterListStorage(const ASTContext &C,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- ArrayRef<NamedDecl *> Params,
- SourceLocation RAngleLoc,
- Expr *RequiresClause)
- : FixedSizeStorageOwner(
- (assert(N == Params.size()),
- assert(HasRequiresClause == (RequiresClause != nullptr)),
- new (static_cast<void *>(&storage)) TemplateParameterList(C,
- TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause))) {}
- };
- /// A template argument list.
- class TemplateArgumentList final
- : private llvm::TrailingObjects<TemplateArgumentList, TemplateArgument> {
- /// The template argument list.
- const TemplateArgument *Arguments;
- /// The number of template arguments in this template
- /// argument list.
- unsigned NumArguments;
- // Constructs an instance with an internal Argument list, containing
- // a copy of the Args array. (Called by CreateCopy)
- TemplateArgumentList(ArrayRef<TemplateArgument> Args);
- public:
- friend TrailingObjects;
- TemplateArgumentList(const TemplateArgumentList &) = delete;
- TemplateArgumentList &operator=(const TemplateArgumentList &) = delete;
- /// Type used to indicate that the template argument list itself is a
- /// stack object. It does not own its template arguments.
- enum OnStackType { OnStack };
- /// Create a new template argument list that copies the given set of
- /// template arguments.
- static TemplateArgumentList *CreateCopy(ASTContext &Context,
- ArrayRef<TemplateArgument> Args);
- /// Construct a new, temporary template argument list on the stack.
- ///
- /// The template argument list does not own the template arguments
- /// provided.
- explicit TemplateArgumentList(OnStackType, ArrayRef<TemplateArgument> Args)
- : Arguments(Args.data()), NumArguments(Args.size()) {}
- /// Produces a shallow copy of the given template argument list.
- ///
- /// This operation assumes that the input argument list outlives it.
- /// This takes the list as a pointer to avoid looking like a copy
- /// constructor, since this really isn't safe to use that way.
- explicit TemplateArgumentList(const TemplateArgumentList *Other)
- : Arguments(Other->data()), NumArguments(Other->size()) {}
- /// Retrieve the template argument at a given index.
- const TemplateArgument &get(unsigned Idx) const {
- assert(Idx < NumArguments && "Invalid template argument index");
- return data()[Idx];
- }
- /// Retrieve the template argument at a given index.
- const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
- /// Produce this as an array ref.
- ArrayRef<TemplateArgument> asArray() const {
- return llvm::ArrayRef(data(), size());
- }
- /// Retrieve the number of template arguments in this
- /// template argument list.
- unsigned size() const { return NumArguments; }
- /// Retrieve a pointer to the template argument list.
- const TemplateArgument *data() const { return Arguments; }
- };
- void *allocateDefaultArgStorageChain(const ASTContext &C);
- /// Storage for a default argument. This is conceptually either empty, or an
- /// argument value, or a pointer to a previous declaration that had a default
- /// argument.
- ///
- /// However, this is complicated by modules: while we require all the default
- /// arguments for a template to be equivalent, there may be more than one, and
- /// we need to track all the originating parameters to determine if the default
- /// argument is visible.
- template<typename ParmDecl, typename ArgType>
- class DefaultArgStorage {
- /// Storage for both the value *and* another parameter from which we inherit
- /// the default argument. This is used when multiple default arguments for a
- /// parameter are merged together from different modules.
- struct Chain {
- ParmDecl *PrevDeclWithDefaultArg;
- ArgType Value;
- };
- static_assert(sizeof(Chain) == sizeof(void *) * 2,
- "non-pointer argument type?");
- llvm::PointerUnion<ArgType, ParmDecl*, Chain*> ValueOrInherited;
- static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) {
- const DefaultArgStorage &Storage = Parm->getDefaultArgStorage();
- if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl *>())
- Parm = Prev;
- assert(!Parm->getDefaultArgStorage()
- .ValueOrInherited.template is<ParmDecl *>() &&
- "should only be one level of indirection");
- return Parm;
- }
- public:
- DefaultArgStorage() : ValueOrInherited(ArgType()) {}
- /// Determine whether there is a default argument for this parameter.
- bool isSet() const { return !ValueOrInherited.isNull(); }
- /// Determine whether the default argument for this parameter was inherited
- /// from a previous declaration of the same entity.
- bool isInherited() const { return ValueOrInherited.template is<ParmDecl*>(); }
- /// Get the default argument's value. This does not consider whether the
- /// default argument is visible.
- ArgType get() const {
- const DefaultArgStorage *Storage = this;
- if (const auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl *>())
- Storage = &Prev->getDefaultArgStorage();
- if (const auto *C = Storage->ValueOrInherited.template dyn_cast<Chain *>())
- return C->Value;
- return Storage->ValueOrInherited.template get<ArgType>();
- }
- /// Get the parameter from which we inherit the default argument, if any.
- /// This is the parameter on which the default argument was actually written.
- const ParmDecl *getInheritedFrom() const {
- if (const auto *D = ValueOrInherited.template dyn_cast<ParmDecl *>())
- return D;
- if (const auto *C = ValueOrInherited.template dyn_cast<Chain *>())
- return C->PrevDeclWithDefaultArg;
- return nullptr;
- }
- /// Set the default argument.
- void set(ArgType Arg) {
- assert(!isSet() && "default argument already set");
- ValueOrInherited = Arg;
- }
- /// Set that the default argument was inherited from another parameter.
- void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) {
- InheritedFrom = getParmOwningDefaultArg(InheritedFrom);
- if (!isSet())
- ValueOrInherited = InheritedFrom;
- else if (auto *D = ValueOrInherited.template dyn_cast<ParmDecl *>()) {
- assert(C.isSameDefaultTemplateArgument(D, InheritedFrom));
- ValueOrInherited =
- new (allocateDefaultArgStorageChain(C)) Chain{InheritedFrom, get()};
- } else if (auto *Inherited =
- ValueOrInherited.template dyn_cast<Chain *>()) {
- assert(C.isSameDefaultTemplateArgument(Inherited->PrevDeclWithDefaultArg,
- InheritedFrom));
- Inherited->PrevDeclWithDefaultArg = InheritedFrom;
- } else
- ValueOrInherited = new (allocateDefaultArgStorageChain(C))
- Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()};
- }
- /// Remove the default argument, even if it was inherited.
- void clear() {
- ValueOrInherited = ArgType();
- }
- };
- //===----------------------------------------------------------------------===//
- // Kinds of Templates
- //===----------------------------------------------------------------------===//
- /// \brief The base class of all kinds of template declarations (e.g.,
- /// class, function, etc.).
- ///
- /// The TemplateDecl class stores the list of template parameters and a
- /// reference to the templated scoped declaration: the underlying AST node.
- class TemplateDecl : public NamedDecl {
- void anchor() override;
- protected:
- // Construct a template decl with name, parameters, and templated element.
- TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl);
- // Construct a template decl with the given name and parameters.
- // Used when there is no templated element (e.g., for tt-params).
- TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params)
- : TemplateDecl(DK, DC, L, Name, Params, nullptr) {}
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- /// Get the list of template parameters
- TemplateParameterList *getTemplateParameters() const {
- return TemplateParams;
- }
- /// \brief Get the total constraint-expression associated with this template,
- /// including constraint-expressions derived from the requires-clause,
- /// trailing requires-clause (for functions and methods) and constrained
- /// template parameters.
- void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const;
- bool hasAssociatedConstraints() const;
- /// Get the underlying, templated declaration.
- NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
- // Should a specialization behave like an alias for another type.
- bool isTypeAlias() const;
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) {
- return K >= firstTemplate && K <= lastTemplate;
- }
- SourceRange getSourceRange() const override LLVM_READONLY {
- return SourceRange(getTemplateParameters()->getTemplateLoc(),
- TemplatedDecl->getSourceRange().getEnd());
- }
- protected:
- NamedDecl *TemplatedDecl;
- TemplateParameterList *TemplateParams;
- public:
- void setTemplateParameters(TemplateParameterList *TParams) {
- TemplateParams = TParams;
- }
- /// Initialize the underlying templated declaration.
- void init(NamedDecl *NewTemplatedDecl) {
- if (TemplatedDecl)
- assert(TemplatedDecl == NewTemplatedDecl && "Inconsistent TemplatedDecl");
- else
- TemplatedDecl = NewTemplatedDecl;
- }
- };
- /// Provides information about a function template specialization,
- /// which is a FunctionDecl that has been explicitly specialization or
- /// instantiated from a function template.
- class FunctionTemplateSpecializationInfo final
- : public llvm::FoldingSetNode,
- private llvm::TrailingObjects<FunctionTemplateSpecializationInfo,
- MemberSpecializationInfo *> {
- /// The function template specialization that this structure describes and a
- /// flag indicating if the function is a member specialization.
- llvm::PointerIntPair<FunctionDecl *, 1, bool> Function;
- /// The function template from which this function template
- /// specialization was generated.
- ///
- /// The two bits contain the top 4 values of TemplateSpecializationKind.
- llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template;
- public:
- /// The template arguments used to produce the function template
- /// specialization from the function template.
- const TemplateArgumentList *TemplateArguments;
- /// The template arguments as written in the sources, if provided.
- /// FIXME: Normally null; tail-allocate this.
- const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten;
- /// The point at which this function template specialization was
- /// first instantiated.
- SourceLocation PointOfInstantiation;
- private:
- FunctionTemplateSpecializationInfo(
- FunctionDecl *FD, FunctionTemplateDecl *Template,
- TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs,
- const ASTTemplateArgumentListInfo *TemplateArgsAsWritten,
- SourceLocation POI, MemberSpecializationInfo *MSInfo)
- : Function(FD, MSInfo ? true : false), Template(Template, TSK - 1),
- TemplateArguments(TemplateArgs),
- TemplateArgumentsAsWritten(TemplateArgsAsWritten),
- PointOfInstantiation(POI) {
- if (MSInfo)
- getTrailingObjects<MemberSpecializationInfo *>()[0] = MSInfo;
- }
- size_t numTrailingObjects(OverloadToken<MemberSpecializationInfo*>) const {
- return Function.getInt();
- }
- public:
- friend TrailingObjects;
- static FunctionTemplateSpecializationInfo *
- Create(ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
- TemplateSpecializationKind TSK,
- const TemplateArgumentList *TemplateArgs,
- const TemplateArgumentListInfo *TemplateArgsAsWritten,
- SourceLocation POI, MemberSpecializationInfo *MSInfo);
- /// Retrieve the declaration of the function template specialization.
- FunctionDecl *getFunction() const { return Function.getPointer(); }
- /// Retrieve the template from which this function was specialized.
- FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); }
- /// Determine what kind of template specialization this is.
- TemplateSpecializationKind getTemplateSpecializationKind() const {
- return (TemplateSpecializationKind)(Template.getInt() + 1);
- }
- bool isExplicitSpecialization() const {
- return getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
- }
- /// True if this declaration is an explicit specialization,
- /// explicit instantiation declaration, or explicit instantiation
- /// definition.
- bool isExplicitInstantiationOrSpecialization() const {
- return isTemplateExplicitInstantiationOrSpecialization(
- getTemplateSpecializationKind());
- }
- /// Set the template specialization kind.
- void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
- assert(TSK != TSK_Undeclared &&
- "Cannot encode TSK_Undeclared for a function template specialization");
- Template.setInt(TSK - 1);
- }
- /// Retrieve the first point of instantiation of this function
- /// template specialization.
- ///
- /// The point of instantiation may be an invalid source location if this
- /// function has yet to be instantiated.
- SourceLocation getPointOfInstantiation() const {
- return PointOfInstantiation;
- }
- /// Set the (first) point of instantiation of this function template
- /// specialization.
- void setPointOfInstantiation(SourceLocation POI) {
- PointOfInstantiation = POI;
- }
- /// Get the specialization info if this function template specialization is
- /// also a member specialization:
- ///
- /// \code
- /// template<typename> struct A {
- /// template<typename> void f();
- /// template<> void f<int>(); // ClassScopeFunctionSpecializationDecl
- /// };
- /// \endcode
- ///
- /// Here, A<int>::f<int> is a function template specialization that is
- /// an explicit specialization of A<int>::f, but it's also a member
- /// specialization (an implicit instantiation in this case) of A::f<int>.
- /// Further:
- ///
- /// \code
- /// template<> template<> void A<int>::f<int>() {}
- /// \endcode
- ///
- /// ... declares a function template specialization that is an explicit
- /// specialization of A<int>::f, and is also an explicit member
- /// specialization of A::f<int>.
- ///
- /// Note that the TemplateSpecializationKind of the MemberSpecializationInfo
- /// need not be the same as that returned by getTemplateSpecializationKind(),
- /// and represents the relationship between the function and the class-scope
- /// explicit specialization in the original templated class -- whereas our
- /// TemplateSpecializationKind represents the relationship between the
- /// function and the function template, and should always be
- /// TSK_ExplicitSpecialization whenever we have MemberSpecializationInfo.
- MemberSpecializationInfo *getMemberSpecializationInfo() const {
- return numTrailingObjects(OverloadToken<MemberSpecializationInfo *>())
- ? getTrailingObjects<MemberSpecializationInfo *>()[0]
- : nullptr;
- }
- void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, TemplateArguments->asArray(), getFunction()->getASTContext());
- }
- static void
- Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
- ASTContext &Context) {
- ID.AddInteger(TemplateArgs.size());
- for (const TemplateArgument &TemplateArg : TemplateArgs)
- TemplateArg.Profile(ID, Context);
- }
- };
- /// Provides information a specialization of a member of a class
- /// template, which may be a member function, static data member,
- /// member class or member enumeration.
- class MemberSpecializationInfo {
- // The member declaration from which this member was instantiated, and the
- // manner in which the instantiation occurred (in the lower two bits).
- llvm::PointerIntPair<NamedDecl *, 2> MemberAndTSK;
- // The point at which this member was first instantiated.
- SourceLocation PointOfInstantiation;
- public:
- explicit
- MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK,
- SourceLocation POI = SourceLocation())
- : MemberAndTSK(IF, TSK - 1), PointOfInstantiation(POI) {
- assert(TSK != TSK_Undeclared &&
- "Cannot encode undeclared template specializations for members");
- }
- /// Retrieve the member declaration from which this member was
- /// instantiated.
- NamedDecl *getInstantiatedFrom() const { return MemberAndTSK.getPointer(); }
- /// Determine what kind of template specialization this is.
- TemplateSpecializationKind getTemplateSpecializationKind() const {
- return (TemplateSpecializationKind)(MemberAndTSK.getInt() + 1);
- }
- bool isExplicitSpecialization() const {
- return getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
- }
- /// Set the template specialization kind.
- void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
- assert(TSK != TSK_Undeclared &&
- "Cannot encode undeclared template specializations for members");
- MemberAndTSK.setInt(TSK - 1);
- }
- /// Retrieve the first point of instantiation of this member.
- /// If the point of instantiation is an invalid location, then this member
- /// has not yet been instantiated.
- SourceLocation getPointOfInstantiation() const {
- return PointOfInstantiation;
- }
- /// Set the first point of instantiation.
- void setPointOfInstantiation(SourceLocation POI) {
- PointOfInstantiation = POI;
- }
- };
- /// Provides information about a dependent function-template
- /// specialization declaration.
- ///
- /// Since explicit function template specialization and instantiation
- /// declarations can only appear in namespace scope, and you can only
- /// specialize a member of a fully-specialized class, the only way to
- /// get one of these is in a friend declaration like the following:
- ///
- /// \code
- /// template \<class T> void foo(T);
- /// template \<class T> class A {
- /// friend void foo<>(T);
- /// };
- /// \endcode
- class DependentFunctionTemplateSpecializationInfo final
- : private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo,
- TemplateArgumentLoc,
- FunctionTemplateDecl *> {
- /// The number of potential template candidates.
- unsigned NumTemplates;
- /// The number of template arguments.
- unsigned NumArgs;
- /// The locations of the left and right angle brackets.
- SourceRange AngleLocs;
- size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
- return NumArgs;
- }
- size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const {
- return NumTemplates;
- }
- DependentFunctionTemplateSpecializationInfo(
- const UnresolvedSetImpl &Templates,
- const TemplateArgumentListInfo &TemplateArgs);
- public:
- friend TrailingObjects;
- static DependentFunctionTemplateSpecializationInfo *
- Create(ASTContext &Context, const UnresolvedSetImpl &Templates,
- const TemplateArgumentListInfo &TemplateArgs);
- /// Returns the number of function templates that this might
- /// be a specialization of.
- unsigned getNumTemplates() const { return NumTemplates; }
- /// Returns the i'th template candidate.
- FunctionTemplateDecl *getTemplate(unsigned I) const {
- assert(I < getNumTemplates() && "template index out of range");
- return getTrailingObjects<FunctionTemplateDecl *>()[I];
- }
- /// Returns the explicit template arguments that were given.
- const TemplateArgumentLoc *getTemplateArgs() const {
- return getTrailingObjects<TemplateArgumentLoc>();
- }
- /// Returns the number of explicit template arguments that were given.
- unsigned getNumTemplateArgs() const { return NumArgs; }
- llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
- return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs());
- }
- /// Returns the nth template argument.
- const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
- assert(I < getNumTemplateArgs() && "template arg index out of range");
- return getTemplateArgs()[I];
- }
- SourceLocation getLAngleLoc() const {
- return AngleLocs.getBegin();
- }
- SourceLocation getRAngleLoc() const {
- return AngleLocs.getEnd();
- }
- };
- /// Declaration of a redeclarable template.
- class RedeclarableTemplateDecl : public TemplateDecl,
- public Redeclarable<RedeclarableTemplateDecl>
- {
- using redeclarable_base = Redeclarable<RedeclarableTemplateDecl>;
- RedeclarableTemplateDecl *getNextRedeclarationImpl() override {
- return getNextRedeclaration();
- }
- RedeclarableTemplateDecl *getPreviousDeclImpl() override {
- return getPreviousDecl();
- }
- RedeclarableTemplateDecl *getMostRecentDeclImpl() override {
- return getMostRecentDecl();
- }
- void anchor() override;
- protected:
- template <typename EntryType> struct SpecEntryTraits {
- using DeclType = EntryType;
- static DeclType *getDecl(EntryType *D) {
- return D;
- }
- static ArrayRef<TemplateArgument> getTemplateArgs(EntryType *D) {
- return D->getTemplateArgs().asArray();
- }
- };
- template <typename EntryType, typename SETraits = SpecEntryTraits<EntryType>,
- typename DeclType = typename SETraits::DeclType>
- struct SpecIterator
- : llvm::iterator_adaptor_base<
- SpecIterator<EntryType, SETraits, DeclType>,
- typename llvm::FoldingSetVector<EntryType>::iterator,
- typename std::iterator_traits<typename llvm::FoldingSetVector<
- EntryType>::iterator>::iterator_category,
- DeclType *, ptrdiff_t, DeclType *, DeclType *> {
- SpecIterator() = default;
- explicit SpecIterator(
- typename llvm::FoldingSetVector<EntryType>::iterator SetIter)
- : SpecIterator::iterator_adaptor_base(std::move(SetIter)) {}
- DeclType *operator*() const {
- return SETraits::getDecl(&*this->I)->getMostRecentDecl();
- }
- DeclType *operator->() const { return **this; }
- };
- template <typename EntryType>
- static SpecIterator<EntryType>
- makeSpecIterator(llvm::FoldingSetVector<EntryType> &Specs, bool isEnd) {
- return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin());
- }
- void loadLazySpecializationsImpl() const;
- template <class EntryType, typename ...ProfileArguments>
- typename SpecEntryTraits<EntryType>::DeclType*
- findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
- void *&InsertPos, ProfileArguments &&...ProfileArgs);
- template <class Derived, class EntryType>
- void addSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
- EntryType *Entry, void *InsertPos);
- struct CommonBase {
- CommonBase() : InstantiatedFromMember(nullptr, false) {}
- /// The template from which this was most
- /// directly instantiated (or null).
- ///
- /// The boolean value indicates whether this template
- /// was explicitly specialized.
- llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
- InstantiatedFromMember;
- /// If non-null, points to an array of specializations (including
- /// partial specializations) known only by their external declaration IDs.
- ///
- /// The first value in the array is the number of specializations/partial
- /// specializations that follow.
- uint32_t *LazySpecializations = nullptr;
- /// The set of "injected" template arguments used within this
- /// template.
- ///
- /// This pointer refers to the template arguments (there are as
- /// many template arguments as template parameaters) for the
- /// template, and is allocated lazily, since most templates do not
- /// require the use of this information.
- TemplateArgument *InjectedArgs = nullptr;
- };
- /// Pointer to the common data shared by all declarations of this
- /// template.
- mutable CommonBase *Common = nullptr;
- /// Retrieves the "common" pointer shared by all (re-)declarations of
- /// the same template. Calling this routine may implicitly allocate memory
- /// for the common pointer.
- CommonBase *getCommonPtr() const;
- virtual CommonBase *newCommon(ASTContext &C) const = 0;
- // Construct a template decl with name, parameters, and templated element.
- RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC,
- SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl)
- : TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C) {}
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- friend class ASTReader;
- template <class decl_type> friend class RedeclarableTemplate;
- /// Retrieves the canonical declaration of this template.
- RedeclarableTemplateDecl *getCanonicalDecl() override {
- return getFirstDecl();
- }
- const RedeclarableTemplateDecl *getCanonicalDecl() const {
- return getFirstDecl();
- }
- /// Determines whether this template was a specialization of a
- /// member template.
- ///
- /// In the following example, the function template \c X<int>::f and the
- /// member template \c X<int>::Inner are member specializations.
- ///
- /// \code
- /// template<typename T>
- /// struct X {
- /// template<typename U> void f(T, U);
- /// template<typename U> struct Inner;
- /// };
- ///
- /// template<> template<typename T>
- /// void X<int>::f(int, T);
- /// template<> template<typename T>
- /// struct X<int>::Inner { /* ... */ };
- /// \endcode
- bool isMemberSpecialization() const {
- return getCommonPtr()->InstantiatedFromMember.getInt();
- }
- /// Note that this member template is a specialization.
- void setMemberSpecialization() {
- assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
- "Only member templates can be member template specializations");
- getCommonPtr()->InstantiatedFromMember.setInt(true);
- }
- /// Retrieve the member template from which this template was
- /// instantiated, or nullptr if this template was not instantiated from a
- /// member template.
- ///
- /// A template is instantiated from a member template when the member
- /// template itself is part of a class template (or member thereof). For
- /// example, given
- ///
- /// \code
- /// template<typename T>
- /// struct X {
- /// template<typename U> void f(T, U);
- /// };
- ///
- /// void test(X<int> x) {
- /// x.f(1, 'a');
- /// };
- /// \endcode
- ///
- /// \c X<int>::f is a FunctionTemplateDecl that describes the function
- /// template
- ///
- /// \code
- /// template<typename U> void X<int>::f(int, U);
- /// \endcode
- ///
- /// which was itself created during the instantiation of \c X<int>. Calling
- /// getInstantiatedFromMemberTemplate() on this FunctionTemplateDecl will
- /// retrieve the FunctionTemplateDecl for the original template \c f within
- /// the class template \c X<T>, i.e.,
- ///
- /// \code
- /// template<typename T>
- /// template<typename U>
- /// void X<T>::f(T, U);
- /// \endcode
- RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const {
- return getCommonPtr()->InstantiatedFromMember.getPointer();
- }
- void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) {
- assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
- getCommonPtr()->InstantiatedFromMember.setPointer(TD);
- }
- /// Retrieve the "injected" template arguments that correspond to the
- /// template parameters of this template.
- ///
- /// Although the C++ standard has no notion of the "injected" template
- /// arguments for a template, the notion is convenient when
- /// we need to perform substitutions inside the definition of a template.
- ArrayRef<TemplateArgument> getInjectedTemplateArgs();
- using redecl_range = redeclarable_base::redecl_range;
- using redecl_iterator = redeclarable_base::redecl_iterator;
- using redeclarable_base::redecls_begin;
- using redeclarable_base::redecls_end;
- using redeclarable_base::redecls;
- using redeclarable_base::getPreviousDecl;
- using redeclarable_base::getMostRecentDecl;
- using redeclarable_base::isFirstDecl;
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) {
- return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
- }
- };
- template <> struct RedeclarableTemplateDecl::
- SpecEntryTraits<FunctionTemplateSpecializationInfo> {
- using DeclType = FunctionDecl;
- static DeclType *getDecl(FunctionTemplateSpecializationInfo *I) {
- return I->getFunction();
- }
- static ArrayRef<TemplateArgument>
- getTemplateArgs(FunctionTemplateSpecializationInfo *I) {
- return I->TemplateArguments->asArray();
- }
- };
- /// Declaration of a template function.
- class FunctionTemplateDecl : public RedeclarableTemplateDecl {
- protected:
- friend class FunctionDecl;
- /// Data that is common to all of the declarations of a given
- /// function template.
- struct Common : CommonBase {
- /// The function template specializations for this function
- /// template, including explicit specializations and instantiations.
- llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations;
- Common() = default;
- };
- FunctionTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
- DeclarationName Name, TemplateParameterList *Params,
- NamedDecl *Decl)
- : RedeclarableTemplateDecl(FunctionTemplate, C, DC, L, Name, Params,
- Decl) {}
- CommonBase *newCommon(ASTContext &C) const override;
- Common *getCommonPtr() const {
- return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
- }
- /// Retrieve the set of function template specializations of this
- /// function template.
- llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
- getSpecializations() const;
- /// Add a specialization of this function template.
- ///
- /// \param InsertPos Insert position in the FoldingSetVector, must have been
- /// retrieved by an earlier call to findSpecialization().
- void addSpecialization(FunctionTemplateSpecializationInfo* Info,
- void *InsertPos);
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- /// Load any lazily-loaded specializations from the external source.
- void LoadLazySpecializations() const;
- /// Get the underlying function declaration of the template.
- FunctionDecl *getTemplatedDecl() const {
- return static_cast<FunctionDecl *>(TemplatedDecl);
- }
- /// Returns whether this template declaration defines the primary
- /// pattern.
- bool isThisDeclarationADefinition() const {
- return getTemplatedDecl()->isThisDeclarationADefinition();
- }
- /// Return the specialization with the provided arguments if it exists,
- /// otherwise return the insertion point.
- FunctionDecl *findSpecialization(ArrayRef<TemplateArgument> Args,
- void *&InsertPos);
- FunctionTemplateDecl *getCanonicalDecl() override {
- return cast<FunctionTemplateDecl>(
- RedeclarableTemplateDecl::getCanonicalDecl());
- }
- const FunctionTemplateDecl *getCanonicalDecl() const {
- return cast<FunctionTemplateDecl>(
- RedeclarableTemplateDecl::getCanonicalDecl());
- }
- /// Retrieve the previous declaration of this function template, or
- /// nullptr if no such declaration exists.
- FunctionTemplateDecl *getPreviousDecl() {
- return cast_or_null<FunctionTemplateDecl>(
- static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
- }
- const FunctionTemplateDecl *getPreviousDecl() const {
- return cast_or_null<FunctionTemplateDecl>(
- static_cast<const RedeclarableTemplateDecl *>(this)->getPreviousDecl());
- }
- FunctionTemplateDecl *getMostRecentDecl() {
- return cast<FunctionTemplateDecl>(
- static_cast<RedeclarableTemplateDecl *>(this)
- ->getMostRecentDecl());
- }
- const FunctionTemplateDecl *getMostRecentDecl() const {
- return const_cast<FunctionTemplateDecl*>(this)->getMostRecentDecl();
- }
- FunctionTemplateDecl *getInstantiatedFromMemberTemplate() const {
- return cast_or_null<FunctionTemplateDecl>(
- RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
- }
- using spec_iterator = SpecIterator<FunctionTemplateSpecializationInfo>;
- using spec_range = llvm::iterator_range<spec_iterator>;
- spec_range specializations() const {
- return spec_range(spec_begin(), spec_end());
- }
- spec_iterator spec_begin() const {
- return makeSpecIterator(getSpecializations(), false);
- }
- spec_iterator spec_end() const {
- return makeSpecIterator(getSpecializations(), true);
- }
- /// Return whether this function template is an abbreviated function template,
- /// e.g. `void foo(auto x)` or `template<typename T> void foo(auto x)`
- bool isAbbreviated() const {
- // Since the invented template parameters generated from 'auto' parameters
- // are either appended to the end of the explicit template parameter list or
- // form a new template parameter list, we can simply observe the last
- // parameter to determine if such a thing happened.
- const TemplateParameterList *TPL = getTemplateParameters();
- return TPL->getParam(TPL->size() - 1)->isImplicit();
- }
- /// Merge \p Prev with our RedeclarableTemplateDecl::Common.
- void mergePrevDecl(FunctionTemplateDecl *Prev);
- /// Create a function template node.
- static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- DeclarationName Name,
- TemplateParameterList *Params,
- NamedDecl *Decl);
- /// Create an empty function template node.
- static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- // Implement isa/cast/dyncast support
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == FunctionTemplate; }
- };
- //===----------------------------------------------------------------------===//
- // Kinds of Template Parameters
- //===----------------------------------------------------------------------===//
- /// Defines the position of a template parameter within a template
- /// parameter list.
- ///
- /// Because template parameter can be listed
- /// sequentially for out-of-line template members, each template parameter is
- /// given a Depth - the nesting of template parameter scopes - and a Position -
- /// the occurrence within the parameter list.
- /// This class is inheritedly privately by different kinds of template
- /// parameters and is not part of the Decl hierarchy. Just a facility.
- class TemplateParmPosition {
- protected:
- enum { DepthWidth = 20, PositionWidth = 12 };
- unsigned Depth : DepthWidth;
- unsigned Position : PositionWidth;
- static constexpr unsigned MaxDepth = (1U << DepthWidth) - 1;
- static constexpr unsigned MaxPosition = (1U << PositionWidth) - 1;
- TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) {
- // The input may fill maximum values to show that it is invalid.
- // Add one here to convert it to zero.
- assert((D + 1) <= MaxDepth &&
- "The depth of template parmeter position is more than 2^20!");
- assert((P + 1) <= MaxPosition &&
- "The position of template parmeter position is more than 2^12!");
- }
- public:
- TemplateParmPosition() = delete;
- /// Get the nesting depth of the template parameter.
- unsigned getDepth() const { return Depth; }
- void setDepth(unsigned D) {
- assert((D + 1) <= MaxDepth &&
- "The depth of template parmeter position is more than 2^20!");
- Depth = D;
- }
- /// Get the position of the template parameter within its parameter list.
- unsigned getPosition() const { return Position; }
- void setPosition(unsigned P) {
- assert((P + 1) <= MaxPosition &&
- "The position of template parmeter position is more than 2^12!");
- Position = P;
- }
- /// Get the index of the template parameter within its parameter list.
- unsigned getIndex() const { return Position; }
- };
- /// Declaration of a template type parameter.
- ///
- /// For example, "T" in
- /// \code
- /// template<typename T> class vector;
- /// \endcode
- class TemplateTypeParmDecl final : public TypeDecl,
- private llvm::TrailingObjects<TemplateTypeParmDecl, TypeConstraint> {
- /// Sema creates these on the stack during auto type deduction.
- friend class Sema;
- friend TrailingObjects;
- friend class ASTDeclReader;
- /// Whether this template type parameter was declaration with
- /// the 'typename' keyword.
- ///
- /// If false, it was declared with the 'class' keyword.
- bool Typename : 1;
- /// Whether this template type parameter has a type-constraint construct.
- bool HasTypeConstraint : 1;
- /// Whether the type constraint has been initialized. This can be false if the
- /// constraint was not initialized yet or if there was an error forming the
- /// type constraint.
- bool TypeConstraintInitialized : 1;
- /// Whether this type template parameter is an "expanded"
- /// parameter pack, meaning that its type is a pack expansion and we
- /// already know the set of types that expansion expands to.
- bool ExpandedParameterPack : 1;
- /// The number of type parameters in an expanded parameter pack.
- unsigned NumExpanded = 0;
- /// The default template argument, if any.
- using DefArgStorage =
- DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *>;
- DefArgStorage DefaultArgument;
- TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc,
- SourceLocation IdLoc, IdentifierInfo *Id, bool Typename,
- bool HasTypeConstraint,
- std::optional<unsigned> NumExpanded)
- : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename),
- HasTypeConstraint(HasTypeConstraint), TypeConstraintInitialized(false),
- ExpandedParameterPack(NumExpanded),
- NumExpanded(NumExpanded.value_or(0)) {}
- public:
- static TemplateTypeParmDecl *
- Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc,
- SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id,
- bool Typename, bool ParameterPack, bool HasTypeConstraint = false,
- std::optional<unsigned> NumExpanded = std::nullopt);
- static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
- unsigned ID);
- static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
- unsigned ID,
- bool HasTypeConstraint);
- /// Whether this template type parameter was declared with
- /// the 'typename' keyword.
- ///
- /// If not, it was either declared with the 'class' keyword or with a
- /// type-constraint (see hasTypeConstraint()).
- bool wasDeclaredWithTypename() const {
- return Typename && !HasTypeConstraint;
- }
- const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
- /// Determine whether this template parameter has a default
- /// argument.
- bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
- /// Retrieve the default argument, if any.
- QualType getDefaultArgument() const {
- return DefaultArgument.get()->getType();
- }
- /// Retrieves the default argument's source information, if any.
- TypeSourceInfo *getDefaultArgumentInfo() const {
- return DefaultArgument.get();
- }
- /// Retrieves the location of the default argument declaration.
- SourceLocation getDefaultArgumentLoc() const;
- /// Determines whether the default argument was inherited
- /// from a previous declaration of this template.
- bool defaultArgumentWasInherited() const {
- return DefaultArgument.isInherited();
- }
- /// Set the default argument for this template parameter.
- void setDefaultArgument(TypeSourceInfo *DefArg) {
- DefaultArgument.set(DefArg);
- }
- /// Set that this default argument was inherited from another
- /// parameter.
- void setInheritedDefaultArgument(const ASTContext &C,
- TemplateTypeParmDecl *Prev) {
- DefaultArgument.setInherited(C, Prev);
- }
- /// Removes the default argument of this template parameter.
- void removeDefaultArgument() {
- DefaultArgument.clear();
- }
- /// Set whether this template type parameter was declared with
- /// the 'typename' or 'class' keyword.
- void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; }
- /// Retrieve the depth of the template parameter.
- unsigned getDepth() const;
- /// Retrieve the index of the template parameter.
- unsigned getIndex() const;
- /// Returns whether this is a parameter pack.
- bool isParameterPack() const;
- /// Whether this parameter pack is a pack expansion.
- ///
- /// A template type template parameter pack can be a pack expansion if its
- /// type-constraint contains an unexpanded parameter pack.
- bool isPackExpansion() const {
- if (!isParameterPack())
- return false;
- if (const TypeConstraint *TC = getTypeConstraint())
- if (TC->hasExplicitTemplateArgs())
- for (const auto &ArgLoc : TC->getTemplateArgsAsWritten()->arguments())
- if (ArgLoc.getArgument().containsUnexpandedParameterPack())
- return true;
- return false;
- }
- /// Whether this parameter is a template type parameter pack that has a known
- /// list of different type-constraints at different positions.
- ///
- /// A parameter pack is an expanded parameter pack when the original
- /// parameter pack's type-constraint was itself a pack expansion, and that
- /// expansion has already been expanded. For example, given:
- ///
- /// \code
- /// template<typename ...Types>
- /// struct X {
- /// template<convertible_to<Types> ...Convertibles>
- /// struct Y { /* ... */ };
- /// };
- /// \endcode
- ///
- /// The parameter pack \c Convertibles has (convertible_to<Types> && ...) as
- /// its type-constraint. When \c Types is supplied with template arguments by
- /// instantiating \c X, the instantiation of \c Convertibles becomes an
- /// expanded parameter pack. For example, instantiating
- /// \c X<int, unsigned int> results in \c Convertibles being an expanded
- /// parameter pack of size 2 (use getNumExpansionTypes() to get this number).
- bool isExpandedParameterPack() const { return ExpandedParameterPack; }
- /// Retrieves the number of parameters in an expanded parameter pack.
- unsigned getNumExpansionParameters() const {
- assert(ExpandedParameterPack && "Not an expansion parameter pack");
- return NumExpanded;
- }
- /// Returns the type constraint associated with this template parameter (if
- /// any).
- const TypeConstraint *getTypeConstraint() const {
- return TypeConstraintInitialized ? getTrailingObjects<TypeConstraint>() :
- nullptr;
- }
- void setTypeConstraint(NestedNameSpecifierLoc NNS,
- DeclarationNameInfo NameInfo, NamedDecl *FoundDecl,
- ConceptDecl *CD,
- const ASTTemplateArgumentListInfo *ArgsAsWritten,
- Expr *ImmediatelyDeclaredConstraint);
- /// Determine whether this template parameter has a type-constraint.
- bool hasTypeConstraint() const {
- return HasTypeConstraint;
- }
- /// \brief Get the associated-constraints of this template parameter.
- /// This will either be the immediately-introduced constraint or empty.
- ///
- /// Use this instead of getTypeConstraint for concepts APIs that
- /// accept an ArrayRef of constraint expressions.
- void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
- if (HasTypeConstraint)
- AC.push_back(getTypeConstraint()->getImmediatelyDeclaredConstraint());
- }
- SourceRange getSourceRange() const override LLVM_READONLY;
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == TemplateTypeParm; }
- };
- /// NonTypeTemplateParmDecl - Declares a non-type template parameter,
- /// e.g., "Size" in
- /// @code
- /// template<int Size> class array { };
- /// @endcode
- class NonTypeTemplateParmDecl final
- : public DeclaratorDecl,
- protected TemplateParmPosition,
- private llvm::TrailingObjects<NonTypeTemplateParmDecl,
- std::pair<QualType, TypeSourceInfo *>,
- Expr *> {
- friend class ASTDeclReader;
- friend TrailingObjects;
- /// The default template argument, if any, and whether or not
- /// it was inherited.
- using DefArgStorage = DefaultArgStorage<NonTypeTemplateParmDecl, Expr *>;
- DefArgStorage DefaultArgument;
- // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index
- // down here to save memory.
- /// Whether this non-type template parameter is a parameter pack.
- bool ParameterPack;
- /// Whether this non-type template parameter is an "expanded"
- /// parameter pack, meaning that its type is a pack expansion and we
- /// already know the set of types that expansion expands to.
- bool ExpandedParameterPack = false;
- /// The number of types in an expanded parameter pack.
- unsigned NumExpandedTypes = 0;
- size_t numTrailingObjects(
- OverloadToken<std::pair<QualType, TypeSourceInfo *>>) const {
- return NumExpandedTypes;
- }
- NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, unsigned D, unsigned P,
- IdentifierInfo *Id, QualType T,
- bool ParameterPack, TypeSourceInfo *TInfo)
- : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
- TemplateParmPosition(D, P), ParameterPack(ParameterPack) {}
- NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, unsigned D, unsigned P,
- IdentifierInfo *Id, QualType T,
- TypeSourceInfo *TInfo,
- ArrayRef<QualType> ExpandedTypes,
- ArrayRef<TypeSourceInfo *> ExpandedTInfos);
- public:
- static NonTypeTemplateParmDecl *
- Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
- QualType T, bool ParameterPack, TypeSourceInfo *TInfo);
- static NonTypeTemplateParmDecl *
- Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
- QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
- ArrayRef<TypeSourceInfo *> ExpandedTInfos);
- static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
- unsigned ID,
- bool HasTypeConstraint);
- static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
- unsigned ID,
- unsigned NumExpandedTypes,
- bool HasTypeConstraint);
- using TemplateParmPosition::getDepth;
- using TemplateParmPosition::setDepth;
- using TemplateParmPosition::getPosition;
- using TemplateParmPosition::setPosition;
- using TemplateParmPosition::getIndex;
- SourceRange getSourceRange() const override LLVM_READONLY;
- const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
- /// Determine whether this template parameter has a default
- /// argument.
- bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
- /// Retrieve the default argument, if any.
- Expr *getDefaultArgument() const { return DefaultArgument.get(); }
- /// Retrieve the location of the default argument, if any.
- SourceLocation getDefaultArgumentLoc() const;
- /// Determines whether the default argument was inherited
- /// from a previous declaration of this template.
- bool defaultArgumentWasInherited() const {
- return DefaultArgument.isInherited();
- }
- /// Set the default argument for this template parameter, and
- /// whether that default argument was inherited from another
- /// declaration.
- void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); }
- void setInheritedDefaultArgument(const ASTContext &C,
- NonTypeTemplateParmDecl *Parm) {
- DefaultArgument.setInherited(C, Parm);
- }
- /// Removes the default argument of this template parameter.
- void removeDefaultArgument() { DefaultArgument.clear(); }
- /// Whether this parameter is a non-type template parameter pack.
- ///
- /// If the parameter is a parameter pack, the type may be a
- /// \c PackExpansionType. In the following example, the \c Dims parameter
- /// is a parameter pack (whose type is 'unsigned').
- ///
- /// \code
- /// template<typename T, unsigned ...Dims> struct multi_array;
- /// \endcode
- bool isParameterPack() const { return ParameterPack; }
- /// Whether this parameter pack is a pack expansion.
- ///
- /// A non-type template parameter pack is a pack expansion if its type
- /// contains an unexpanded parameter pack. In this case, we will have
- /// built a PackExpansionType wrapping the type.
- bool isPackExpansion() const {
- return ParameterPack && getType()->getAs<PackExpansionType>();
- }
- /// Whether this parameter is a non-type template parameter pack
- /// that has a known list of different types at different positions.
- ///
- /// A parameter pack is an expanded parameter pack when the original
- /// parameter pack's type was itself a pack expansion, and that expansion
- /// has already been expanded. For example, given:
- ///
- /// \code
- /// template<typename ...Types>
- /// struct X {
- /// template<Types ...Values>
- /// struct Y { /* ... */ };
- /// };
- /// \endcode
- ///
- /// The parameter pack \c Values has a \c PackExpansionType as its type,
- /// which expands \c Types. When \c Types is supplied with template arguments
- /// by instantiating \c X, the instantiation of \c Values becomes an
- /// expanded parameter pack. For example, instantiating
- /// \c X<int, unsigned int> results in \c Values being an expanded parameter
- /// pack with expansion types \c int and \c unsigned int.
- ///
- /// The \c getExpansionType() and \c getExpansionTypeSourceInfo() functions
- /// return the expansion types.
- bool isExpandedParameterPack() const { return ExpandedParameterPack; }
- /// Retrieves the number of expansion types in an expanded parameter
- /// pack.
- unsigned getNumExpansionTypes() const {
- assert(ExpandedParameterPack && "Not an expansion parameter pack");
- return NumExpandedTypes;
- }
- /// Retrieve a particular expansion type within an expanded parameter
- /// pack.
- QualType getExpansionType(unsigned I) const {
- assert(I < NumExpandedTypes && "Out-of-range expansion type index");
- auto TypesAndInfos =
- getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
- return TypesAndInfos[I].first;
- }
- /// Retrieve a particular expansion type source info within an
- /// expanded parameter pack.
- TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const {
- assert(I < NumExpandedTypes && "Out-of-range expansion type index");
- auto TypesAndInfos =
- getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
- return TypesAndInfos[I].second;
- }
- /// Return the constraint introduced by the placeholder type of this non-type
- /// template parameter (if any).
- Expr *getPlaceholderTypeConstraint() const {
- return hasPlaceholderTypeConstraint() ? *getTrailingObjects<Expr *>() :
- nullptr;
- }
- void setPlaceholderTypeConstraint(Expr *E) {
- *getTrailingObjects<Expr *>() = E;
- }
- /// Determine whether this non-type template parameter's type has a
- /// placeholder with a type-constraint.
- bool hasPlaceholderTypeConstraint() const {
- auto *AT = getType()->getContainedAutoType();
- return AT && AT->isConstrained();
- }
- /// \brief Get the associated-constraints of this template parameter.
- /// This will either be a vector of size 1 containing the immediately-declared
- /// constraint introduced by the placeholder type, or an empty vector.
- ///
- /// Use this instead of getPlaceholderImmediatelyDeclaredConstraint for
- /// concepts APIs that accept an ArrayRef of constraint expressions.
- void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
- if (Expr *E = getPlaceholderTypeConstraint())
- AC.push_back(E);
- }
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == NonTypeTemplateParm; }
- };
- /// TemplateTemplateParmDecl - Declares a template template parameter,
- /// e.g., "T" in
- /// @code
- /// template <template <typename> class T> class container { };
- /// @endcode
- /// A template template parameter is a TemplateDecl because it defines the
- /// name of a template and the template parameters allowable for substitution.
- class TemplateTemplateParmDecl final
- : public TemplateDecl,
- protected TemplateParmPosition,
- private llvm::TrailingObjects<TemplateTemplateParmDecl,
- TemplateParameterList *> {
- /// The default template argument, if any.
- using DefArgStorage =
- DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>;
- DefArgStorage DefaultArgument;
- /// Whether this parameter is a parameter pack.
- bool ParameterPack;
- /// Whether this template template parameter is an "expanded"
- /// parameter pack, meaning that it is a pack expansion and we
- /// already know the set of template parameters that expansion expands to.
- bool ExpandedParameterPack = false;
- /// The number of parameters in an expanded parameter pack.
- unsigned NumExpandedParams = 0;
- TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
- unsigned D, unsigned P, bool ParameterPack,
- IdentifierInfo *Id, TemplateParameterList *Params)
- : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
- TemplateParmPosition(D, P), ParameterPack(ParameterPack) {}
- TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
- unsigned D, unsigned P,
- IdentifierInfo *Id, TemplateParameterList *Params,
- ArrayRef<TemplateParameterList *> Expansions);
- void anchor() override;
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- friend TrailingObjects;
- static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
- SourceLocation L, unsigned D,
- unsigned P, bool ParameterPack,
- IdentifierInfo *Id,
- TemplateParameterList *Params);
- static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
- SourceLocation L, unsigned D,
- unsigned P,
- IdentifierInfo *Id,
- TemplateParameterList *Params,
- ArrayRef<TemplateParameterList *> Expansions);
- static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
- unsigned ID);
- static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
- unsigned ID,
- unsigned NumExpansions);
- using TemplateParmPosition::getDepth;
- using TemplateParmPosition::setDepth;
- using TemplateParmPosition::getPosition;
- using TemplateParmPosition::setPosition;
- using TemplateParmPosition::getIndex;
- /// Whether this template template parameter is a template
- /// parameter pack.
- ///
- /// \code
- /// template<template <class T> ...MetaFunctions> struct Apply;
- /// \endcode
- bool isParameterPack() const { return ParameterPack; }
- /// Whether this parameter pack is a pack expansion.
- ///
- /// A template template parameter pack is a pack expansion if its template
- /// parameter list contains an unexpanded parameter pack.
- bool isPackExpansion() const {
- return ParameterPack &&
- getTemplateParameters()->containsUnexpandedParameterPack();
- }
- /// Whether this parameter is a template template parameter pack that
- /// has a known list of different template parameter lists at different
- /// positions.
- ///
- /// A parameter pack is an expanded parameter pack when the original parameter
- /// pack's template parameter list was itself a pack expansion, and that
- /// expansion has already been expanded. For exampe, given:
- ///
- /// \code
- /// template<typename...Types> struct Outer {
- /// template<template<Types> class...Templates> struct Inner;
- /// };
- /// \endcode
- ///
- /// The parameter pack \c Templates is a pack expansion, which expands the
- /// pack \c Types. When \c Types is supplied with template arguments by
- /// instantiating \c Outer, the instantiation of \c Templates is an expanded
- /// parameter pack.
- bool isExpandedParameterPack() const { return ExpandedParameterPack; }
- /// Retrieves the number of expansion template parameters in
- /// an expanded parameter pack.
- unsigned getNumExpansionTemplateParameters() const {
- assert(ExpandedParameterPack && "Not an expansion parameter pack");
- return NumExpandedParams;
- }
- /// Retrieve a particular expansion type within an expanded parameter
- /// pack.
- TemplateParameterList *getExpansionTemplateParameters(unsigned I) const {
- assert(I < NumExpandedParams && "Out-of-range expansion type index");
- return getTrailingObjects<TemplateParameterList *>()[I];
- }
- const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
- /// Determine whether this template parameter has a default
- /// argument.
- bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
- /// Retrieve the default argument, if any.
- const TemplateArgumentLoc &getDefaultArgument() const {
- static const TemplateArgumentLoc NoneLoc;
- return DefaultArgument.isSet() ? *DefaultArgument.get() : NoneLoc;
- }
- /// Retrieve the location of the default argument, if any.
- SourceLocation getDefaultArgumentLoc() const;
- /// Determines whether the default argument was inherited
- /// from a previous declaration of this template.
- bool defaultArgumentWasInherited() const {
- return DefaultArgument.isInherited();
- }
- /// Set the default argument for this template parameter, and
- /// whether that default argument was inherited from another
- /// declaration.
- void setDefaultArgument(const ASTContext &C,
- const TemplateArgumentLoc &DefArg);
- void setInheritedDefaultArgument(const ASTContext &C,
- TemplateTemplateParmDecl *Prev) {
- DefaultArgument.setInherited(C, Prev);
- }
- /// Removes the default argument of this template parameter.
- void removeDefaultArgument() { DefaultArgument.clear(); }
- SourceRange getSourceRange() const override LLVM_READONLY {
- SourceLocation End = getLocation();
- if (hasDefaultArgument() && !defaultArgumentWasInherited())
- End = getDefaultArgument().getSourceRange().getEnd();
- return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
- }
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
- };
- /// Represents the builtin template declaration which is used to
- /// implement __make_integer_seq and other builtin templates. It serves
- /// no real purpose beyond existing as a place to hold template parameters.
- class BuiltinTemplateDecl : public TemplateDecl {
- BuiltinTemplateKind BTK;
- BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
- DeclarationName Name, BuiltinTemplateKind BTK);
- void anchor() override;
- public:
- // Implement isa/cast/dyncast support
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == BuiltinTemplate; }
- static BuiltinTemplateDecl *Create(const ASTContext &C, DeclContext *DC,
- DeclarationName Name,
- BuiltinTemplateKind BTK) {
- return new (C, DC) BuiltinTemplateDecl(C, DC, Name, BTK);
- }
- SourceRange getSourceRange() const override LLVM_READONLY {
- return {};
- }
- BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
- };
- /// Represents a class template specialization, which refers to
- /// a class template with a given set of template arguments.
- ///
- /// Class template specializations represent both explicit
- /// specialization of class templates, as in the example below, and
- /// implicit instantiations of class templates.
- ///
- /// \code
- /// template<typename T> class array;
- ///
- /// template<>
- /// class array<bool> { }; // class template specialization array<bool>
- /// \endcode
- class ClassTemplateSpecializationDecl
- : public CXXRecordDecl, public llvm::FoldingSetNode {
- /// Structure that stores information about a class template
- /// specialization that was instantiated from a class template partial
- /// specialization.
- struct SpecializedPartialSpecialization {
- /// The class template partial specialization from which this
- /// class template specialization was instantiated.
- ClassTemplatePartialSpecializationDecl *PartialSpecialization;
- /// The template argument list deduced for the class template
- /// partial specialization itself.
- const TemplateArgumentList *TemplateArgs;
- };
- /// The template that this specialization specializes
- llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *>
- SpecializedTemplate;
- /// Further info for explicit template specialization/instantiation.
- struct ExplicitSpecializationInfo {
- /// The type-as-written.
- TypeSourceInfo *TypeAsWritten = nullptr;
- /// The location of the extern keyword.
- SourceLocation ExternLoc;
- /// The location of the template keyword.
- SourceLocation TemplateKeywordLoc;
- ExplicitSpecializationInfo() = default;
- };
- /// Further info for explicit template specialization/instantiation.
- /// Does not apply to implicit specializations.
- ExplicitSpecializationInfo *ExplicitInfo = nullptr;
- /// The template arguments used to describe this specialization.
- const TemplateArgumentList *TemplateArgs;
- /// The point where this template was instantiated (if any)
- SourceLocation PointOfInstantiation;
- /// The kind of specialization this declaration refers to.
- /// Really a value of type TemplateSpecializationKind.
- unsigned SpecializationKind : 3;
- protected:
- ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
- DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc,
- ClassTemplateDecl *SpecializedTemplate,
- ArrayRef<TemplateArgument> Args,
- ClassTemplateSpecializationDecl *PrevDecl);
- explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- static ClassTemplateSpecializationDecl *
- Create(ASTContext &Context, TagKind TK, DeclContext *DC,
- SourceLocation StartLoc, SourceLocation IdLoc,
- ClassTemplateDecl *SpecializedTemplate,
- ArrayRef<TemplateArgument> Args,
- ClassTemplateSpecializationDecl *PrevDecl);
- static ClassTemplateSpecializationDecl *
- CreateDeserialized(ASTContext &C, unsigned ID);
- void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
- bool Qualified) const override;
- // FIXME: This is broken. CXXRecordDecl::getMostRecentDecl() returns a
- // different "most recent" declaration from this function for the same
- // declaration, because we don't override getMostRecentDeclImpl(). But
- // it's not clear that we should override that, because the most recent
- // declaration as a CXXRecordDecl sometimes is the injected-class-name.
- ClassTemplateSpecializationDecl *getMostRecentDecl() {
- return cast<ClassTemplateSpecializationDecl>(
- getMostRecentNonInjectedDecl());
- }
- /// Retrieve the template that this specialization specializes.
- ClassTemplateDecl *getSpecializedTemplate() const;
- /// Retrieve the template arguments of the class template
- /// specialization.
- const TemplateArgumentList &getTemplateArgs() const {
- return *TemplateArgs;
- }
- void setTemplateArgs(TemplateArgumentList *Args) {
- TemplateArgs = Args;
- }
- /// Determine the kind of specialization that this
- /// declaration represents.
- TemplateSpecializationKind getSpecializationKind() const {
- return static_cast<TemplateSpecializationKind>(SpecializationKind);
- }
- bool isExplicitSpecialization() const {
- return getSpecializationKind() == TSK_ExplicitSpecialization;
- }
- /// Is this an explicit specialization at class scope (within the class that
- /// owns the primary template)? For example:
- ///
- /// \code
- /// template<typename T> struct Outer {
- /// template<typename U> struct Inner;
- /// template<> struct Inner; // class-scope explicit specialization
- /// };
- /// \endcode
- bool isClassScopeExplicitSpecialization() const {
- return isExplicitSpecialization() &&
- isa<CXXRecordDecl>(getLexicalDeclContext());
- }
- /// True if this declaration is an explicit specialization,
- /// explicit instantiation declaration, or explicit instantiation
- /// definition.
- bool isExplicitInstantiationOrSpecialization() const {
- return isTemplateExplicitInstantiationOrSpecialization(
- getTemplateSpecializationKind());
- }
- void setSpecializedTemplate(ClassTemplateDecl *Specialized) {
- SpecializedTemplate = Specialized;
- }
- void setSpecializationKind(TemplateSpecializationKind TSK) {
- SpecializationKind = TSK;
- }
- /// Get the point of instantiation (if any), or null if none.
- SourceLocation getPointOfInstantiation() const {
- return PointOfInstantiation;
- }
- void setPointOfInstantiation(SourceLocation Loc) {
- assert(Loc.isValid() && "point of instantiation must be valid!");
- PointOfInstantiation = Loc;
- }
- /// If this class template specialization is an instantiation of
- /// a template (rather than an explicit specialization), return the
- /// class template or class template partial specialization from which it
- /// was instantiated.
- llvm::PointerUnion<ClassTemplateDecl *,
- ClassTemplatePartialSpecializationDecl *>
- getInstantiatedFrom() const {
- if (!isTemplateInstantiation(getSpecializationKind()))
- return llvm::PointerUnion<ClassTemplateDecl *,
- ClassTemplatePartialSpecializationDecl *>();
- return getSpecializedTemplateOrPartial();
- }
- /// Retrieve the class template or class template partial
- /// specialization which was specialized by this.
- llvm::PointerUnion<ClassTemplateDecl *,
- ClassTemplatePartialSpecializationDecl *>
- getSpecializedTemplateOrPartial() const {
- if (const auto *PartialSpec =
- SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
- return PartialSpec->PartialSpecialization;
- return SpecializedTemplate.get<ClassTemplateDecl*>();
- }
- /// Retrieve the set of template arguments that should be used
- /// to instantiate members of the class template or class template partial
- /// specialization from which this class template specialization was
- /// instantiated.
- ///
- /// \returns For a class template specialization instantiated from the primary
- /// template, this function will return the same template arguments as
- /// getTemplateArgs(). For a class template specialization instantiated from
- /// a class template partial specialization, this function will return the
- /// deduced template arguments for the class template partial specialization
- /// itself.
- const TemplateArgumentList &getTemplateInstantiationArgs() const {
- if (const auto *PartialSpec =
- SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
- return *PartialSpec->TemplateArgs;
- return getTemplateArgs();
- }
- /// Note that this class template specialization is actually an
- /// instantiation of the given class template partial specialization whose
- /// template arguments have been deduced.
- void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
- const TemplateArgumentList *TemplateArgs) {
- assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
- "Already set to a class template partial specialization!");
- auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
- PS->PartialSpecialization = PartialSpec;
- PS->TemplateArgs = TemplateArgs;
- SpecializedTemplate = PS;
- }
- /// Note that this class template specialization is an instantiation
- /// of the given class template.
- void setInstantiationOf(ClassTemplateDecl *TemplDecl) {
- assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
- "Previously set to a class template partial specialization!");
- SpecializedTemplate = TemplDecl;
- }
- /// Sets the type of this specialization as it was written by
- /// the user. This will be a class template specialization type.
- void setTypeAsWritten(TypeSourceInfo *T) {
- if (!ExplicitInfo)
- ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
- ExplicitInfo->TypeAsWritten = T;
- }
- /// Gets the type of this specialization as it was written by
- /// the user, if it was so written.
- TypeSourceInfo *getTypeAsWritten() const {
- return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
- }
- /// Gets the location of the extern keyword, if present.
- SourceLocation getExternLoc() const {
- return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
- }
- /// Sets the location of the extern keyword.
- void setExternLoc(SourceLocation Loc) {
- if (!ExplicitInfo)
- ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
- ExplicitInfo->ExternLoc = Loc;
- }
- /// Sets the location of the template keyword.
- void setTemplateKeywordLoc(SourceLocation Loc) {
- if (!ExplicitInfo)
- ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
- ExplicitInfo->TemplateKeywordLoc = Loc;
- }
- /// Gets the location of the template keyword, if present.
- SourceLocation getTemplateKeywordLoc() const {
- return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
- }
- SourceRange getSourceRange() const override LLVM_READONLY;
- void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, TemplateArgs->asArray(), getASTContext());
- }
- static void
- Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
- ASTContext &Context) {
- ID.AddInteger(TemplateArgs.size());
- for (const TemplateArgument &TemplateArg : TemplateArgs)
- TemplateArg.Profile(ID, Context);
- }
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) {
- return K >= firstClassTemplateSpecialization &&
- K <= lastClassTemplateSpecialization;
- }
- };
- class ClassTemplatePartialSpecializationDecl
- : public ClassTemplateSpecializationDecl {
- /// The list of template parameters
- TemplateParameterList* TemplateParams = nullptr;
- /// The source info for the template arguments as written.
- /// FIXME: redundant with TypeAsWritten?
- const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
- /// The class template partial specialization from which this
- /// class template partial specialization was instantiated.
- ///
- /// The boolean value will be true to indicate that this class template
- /// partial specialization was specialized at this level.
- llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool>
- InstantiatedFromMember;
- ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
- DeclContext *DC,
- SourceLocation StartLoc,
- SourceLocation IdLoc,
- TemplateParameterList *Params,
- ClassTemplateDecl *SpecializedTemplate,
- ArrayRef<TemplateArgument> Args,
- const ASTTemplateArgumentListInfo *ArgsAsWritten,
- ClassTemplatePartialSpecializationDecl *PrevDecl);
- ClassTemplatePartialSpecializationDecl(ASTContext &C)
- : ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization),
- InstantiatedFromMember(nullptr, false) {}
- void anchor() override;
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- static ClassTemplatePartialSpecializationDecl *
- Create(ASTContext &Context, TagKind TK, DeclContext *DC,
- SourceLocation StartLoc, SourceLocation IdLoc,
- TemplateParameterList *Params,
- ClassTemplateDecl *SpecializedTemplate,
- ArrayRef<TemplateArgument> Args,
- const TemplateArgumentListInfo &ArgInfos,
- QualType CanonInjectedType,
- ClassTemplatePartialSpecializationDecl *PrevDecl);
- static ClassTemplatePartialSpecializationDecl *
- CreateDeserialized(ASTContext &C, unsigned ID);
- ClassTemplatePartialSpecializationDecl *getMostRecentDecl() {
- return cast<ClassTemplatePartialSpecializationDecl>(
- static_cast<ClassTemplateSpecializationDecl *>(
- this)->getMostRecentDecl());
- }
- /// Get the list of template parameters
- TemplateParameterList *getTemplateParameters() const {
- return TemplateParams;
- }
- /// \brief All associated constraints of this partial specialization,
- /// including the requires clause and any constraints derived from
- /// constrained-parameters.
- ///
- /// The constraints in the resulting list are to be treated as if in a
- /// conjunction ("and").
- void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
- TemplateParams->getAssociatedConstraints(AC);
- }
- bool hasAssociatedConstraints() const {
- return TemplateParams->hasAssociatedConstraints();
- }
- /// Get the template arguments as written.
- const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
- return ArgsAsWritten;
- }
- /// Retrieve the member class template partial specialization from
- /// which this particular class template partial specialization was
- /// instantiated.
- ///
- /// \code
- /// template<typename T>
- /// struct Outer {
- /// template<typename U> struct Inner;
- /// template<typename U> struct Inner<U*> { }; // #1
- /// };
- ///
- /// Outer<float>::Inner<int*> ii;
- /// \endcode
- ///
- /// In this example, the instantiation of \c Outer<float>::Inner<int*> will
- /// end up instantiating the partial specialization
- /// \c Outer<float>::Inner<U*>, which itself was instantiated from the class
- /// template partial specialization \c Outer<T>::Inner<U*>. Given
- /// \c Outer<float>::Inner<U*>, this function would return
- /// \c Outer<T>::Inner<U*>.
- ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
- const auto *First =
- cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
- return First->InstantiatedFromMember.getPointer();
- }
- ClassTemplatePartialSpecializationDecl *
- getInstantiatedFromMemberTemplate() const {
- return getInstantiatedFromMember();
- }
- void setInstantiatedFromMember(
- ClassTemplatePartialSpecializationDecl *PartialSpec) {
- auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
- First->InstantiatedFromMember.setPointer(PartialSpec);
- }
- /// Determines whether this class template partial specialization
- /// template was a specialization of a member partial specialization.
- ///
- /// In the following example, the member template partial specialization
- /// \c X<int>::Inner<T*> is a member specialization.
- ///
- /// \code
- /// template<typename T>
- /// struct X {
- /// template<typename U> struct Inner;
- /// template<typename U> struct Inner<U*>;
- /// };
- ///
- /// template<> template<typename T>
- /// struct X<int>::Inner<T*> { /* ... */ };
- /// \endcode
- bool isMemberSpecialization() {
- const auto *First =
- cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
- return First->InstantiatedFromMember.getInt();
- }
- /// Note that this member template is a specialization.
- void setMemberSpecialization() {
- auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
- assert(First->InstantiatedFromMember.getPointer() &&
- "Only member templates can be member template specializations");
- return First->InstantiatedFromMember.setInt(true);
- }
- /// Retrieves the injected specialization type for this partial
- /// specialization. This is not the same as the type-decl-type for
- /// this partial specialization, which is an InjectedClassNameType.
- QualType getInjectedSpecializationType() const {
- assert(getTypeForDecl() && "partial specialization has no type set!");
- return cast<InjectedClassNameType>(getTypeForDecl())
- ->getInjectedSpecializationType();
- }
- void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(),
- getASTContext());
- }
- static void
- Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
- TemplateParameterList *TPL, ASTContext &Context);
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) {
- return K == ClassTemplatePartialSpecialization;
- }
- };
- /// Declaration of a class template.
- class ClassTemplateDecl : public RedeclarableTemplateDecl {
- protected:
- /// Data that is common to all of the declarations of a given
- /// class template.
- struct Common : CommonBase {
- /// The class template specializations for this class
- /// template, including explicit specializations and instantiations.
- llvm::FoldingSetVector<ClassTemplateSpecializationDecl> Specializations;
- /// The class template partial specializations for this class
- /// template.
- llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl>
- PartialSpecializations;
- /// The injected-class-name type for this class template.
- QualType InjectedClassNameType;
- Common() = default;
- };
- /// Retrieve the set of specializations of this class template.
- llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
- getSpecializations() const;
- /// Retrieve the set of partial specializations of this class
- /// template.
- llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
- getPartialSpecializations() const;
- ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
- DeclarationName Name, TemplateParameterList *Params,
- NamedDecl *Decl)
- : RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {}
- CommonBase *newCommon(ASTContext &C) const override;
- Common *getCommonPtr() const {
- return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
- }
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- /// Load any lazily-loaded specializations from the external source.
- void LoadLazySpecializations() const;
- /// Get the underlying class declarations of the template.
- CXXRecordDecl *getTemplatedDecl() const {
- return static_cast<CXXRecordDecl *>(TemplatedDecl);
- }
- /// Returns whether this template declaration defines the primary
- /// class pattern.
- bool isThisDeclarationADefinition() const {
- return getTemplatedDecl()->isThisDeclarationADefinition();
- }
- /// \brief Create a class template node.
- static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- DeclarationName Name,
- TemplateParameterList *Params,
- NamedDecl *Decl);
- /// Create an empty class template node.
- static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- /// Return the specialization with the provided arguments if it exists,
- /// otherwise return the insertion point.
- ClassTemplateSpecializationDecl *
- findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos);
- /// Insert the specified specialization knowing that it is not already
- /// in. InsertPos must be obtained from findSpecialization.
- void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos);
- ClassTemplateDecl *getCanonicalDecl() override {
- return cast<ClassTemplateDecl>(
- RedeclarableTemplateDecl::getCanonicalDecl());
- }
- const ClassTemplateDecl *getCanonicalDecl() const {
- return cast<ClassTemplateDecl>(
- RedeclarableTemplateDecl::getCanonicalDecl());
- }
- /// Retrieve the previous declaration of this class template, or
- /// nullptr if no such declaration exists.
- ClassTemplateDecl *getPreviousDecl() {
- return cast_or_null<ClassTemplateDecl>(
- static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
- }
- const ClassTemplateDecl *getPreviousDecl() const {
- return cast_or_null<ClassTemplateDecl>(
- static_cast<const RedeclarableTemplateDecl *>(
- this)->getPreviousDecl());
- }
- ClassTemplateDecl *getMostRecentDecl() {
- return cast<ClassTemplateDecl>(
- static_cast<RedeclarableTemplateDecl *>(this)->getMostRecentDecl());
- }
- const ClassTemplateDecl *getMostRecentDecl() const {
- return const_cast<ClassTemplateDecl*>(this)->getMostRecentDecl();
- }
- ClassTemplateDecl *getInstantiatedFromMemberTemplate() const {
- return cast_or_null<ClassTemplateDecl>(
- RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
- }
- /// Return the partial specialization with the provided arguments if it
- /// exists, otherwise return the insertion point.
- ClassTemplatePartialSpecializationDecl *
- findPartialSpecialization(ArrayRef<TemplateArgument> Args,
- TemplateParameterList *TPL, void *&InsertPos);
- /// Insert the specified partial specialization knowing that it is not
- /// already in. InsertPos must be obtained from findPartialSpecialization.
- void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
- void *InsertPos);
- /// Retrieve the partial specializations as an ordered list.
- void getPartialSpecializations(
- SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) const;
- /// Find a class template partial specialization with the given
- /// type T.
- ///
- /// \param T a dependent type that names a specialization of this class
- /// template.
- ///
- /// \returns the class template partial specialization that exactly matches
- /// the type \p T, or nullptr if no such partial specialization exists.
- ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T);
- /// Find a class template partial specialization which was instantiated
- /// from the given member partial specialization.
- ///
- /// \param D a member class template partial specialization.
- ///
- /// \returns the class template partial specialization which was instantiated
- /// from the given member partial specialization, or nullptr if no such
- /// partial specialization exists.
- ClassTemplatePartialSpecializationDecl *
- findPartialSpecInstantiatedFromMember(
- ClassTemplatePartialSpecializationDecl *D);
- /// Retrieve the template specialization type of the
- /// injected-class-name for this class template.
- ///
- /// The injected-class-name for a class template \c X is \c
- /// X<template-args>, where \c template-args is formed from the
- /// template arguments that correspond to the template parameters of
- /// \c X. For example:
- ///
- /// \code
- /// template<typename T, int N>
- /// struct array {
- /// typedef array this_type; // "array" is equivalent to "array<T, N>"
- /// };
- /// \endcode
- QualType getInjectedClassNameSpecialization();
- using spec_iterator = SpecIterator<ClassTemplateSpecializationDecl>;
- using spec_range = llvm::iterator_range<spec_iterator>;
- spec_range specializations() const {
- return spec_range(spec_begin(), spec_end());
- }
- spec_iterator spec_begin() const {
- return makeSpecIterator(getSpecializations(), false);
- }
- spec_iterator spec_end() const {
- return makeSpecIterator(getSpecializations(), true);
- }
- // Implement isa/cast/dyncast support
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == ClassTemplate; }
- };
- /// Declaration of a friend template.
- ///
- /// For example:
- /// \code
- /// template \<typename T> class A {
- /// friend class MyVector<T>; // not a friend template
- /// template \<typename U> friend class B; // not a friend template
- /// template \<typename U> friend class Foo<T>::Nested; // friend template
- /// };
- /// \endcode
- ///
- /// \note This class is not currently in use. All of the above
- /// will yield a FriendDecl, not a FriendTemplateDecl.
- class FriendTemplateDecl : public Decl {
- virtual void anchor();
- public:
- using FriendUnion = llvm::PointerUnion<NamedDecl *,TypeSourceInfo *>;
- private:
- // The number of template parameters; always non-zero.
- unsigned NumParams = 0;
- // The parameter list.
- TemplateParameterList **Params = nullptr;
- // The declaration that's a friend of this class.
- FriendUnion Friend;
- // Location of the 'friend' specifier.
- SourceLocation FriendLoc;
- FriendTemplateDecl(DeclContext *DC, SourceLocation Loc,
- TemplateParameterList **Params, unsigned NumParams,
- FriendUnion Friend, SourceLocation FriendLoc)
- : Decl(Decl::FriendTemplate, DC, Loc), NumParams(NumParams),
- Params(Params), Friend(Friend), FriendLoc(FriendLoc) {}
- FriendTemplateDecl(EmptyShell Empty) : Decl(Decl::FriendTemplate, Empty) {}
- public:
- friend class ASTDeclReader;
- static FriendTemplateDecl *
- Create(ASTContext &Context, DeclContext *DC, SourceLocation Loc,
- MutableArrayRef<TemplateParameterList *> Params, FriendUnion Friend,
- SourceLocation FriendLoc);
- static FriendTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- /// If this friend declaration names a templated type (or
- /// a dependent member type of a templated type), return that
- /// type; otherwise return null.
- TypeSourceInfo *getFriendType() const {
- return Friend.dyn_cast<TypeSourceInfo*>();
- }
- /// If this friend declaration names a templated function (or
- /// a member function of a templated type), return that type;
- /// otherwise return null.
- NamedDecl *getFriendDecl() const {
- return Friend.dyn_cast<NamedDecl*>();
- }
- /// Retrieves the location of the 'friend' keyword.
- SourceLocation getFriendLoc() const {
- return FriendLoc;
- }
- TemplateParameterList *getTemplateParameterList(unsigned i) const {
- assert(i <= NumParams);
- return Params[i];
- }
- unsigned getNumTemplateParameters() const {
- return NumParams;
- }
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == Decl::FriendTemplate; }
- };
- /// Declaration of an alias template.
- ///
- /// For example:
- /// \code
- /// template \<typename T> using V = std::map<T*, int, MyCompare<T>>;
- /// \endcode
- class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
- protected:
- using Common = CommonBase;
- TypeAliasTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
- DeclarationName Name, TemplateParameterList *Params,
- NamedDecl *Decl)
- : RedeclarableTemplateDecl(TypeAliasTemplate, C, DC, L, Name, Params,
- Decl) {}
- CommonBase *newCommon(ASTContext &C) const override;
- Common *getCommonPtr() {
- return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
- }
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- /// Get the underlying function declaration of the template.
- TypeAliasDecl *getTemplatedDecl() const {
- return static_cast<TypeAliasDecl *>(TemplatedDecl);
- }
- TypeAliasTemplateDecl *getCanonicalDecl() override {
- return cast<TypeAliasTemplateDecl>(
- RedeclarableTemplateDecl::getCanonicalDecl());
- }
- const TypeAliasTemplateDecl *getCanonicalDecl() const {
- return cast<TypeAliasTemplateDecl>(
- RedeclarableTemplateDecl::getCanonicalDecl());
- }
- /// Retrieve the previous declaration of this function template, or
- /// nullptr if no such declaration exists.
- TypeAliasTemplateDecl *getPreviousDecl() {
- return cast_or_null<TypeAliasTemplateDecl>(
- static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
- }
- const TypeAliasTemplateDecl *getPreviousDecl() const {
- return cast_or_null<TypeAliasTemplateDecl>(
- static_cast<const RedeclarableTemplateDecl *>(
- this)->getPreviousDecl());
- }
- TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() const {
- return cast_or_null<TypeAliasTemplateDecl>(
- RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
- }
- /// Create a function template node.
- static TypeAliasTemplateDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- DeclarationName Name,
- TemplateParameterList *Params,
- NamedDecl *Decl);
- /// Create an empty alias template node.
- static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- // Implement isa/cast/dyncast support
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == TypeAliasTemplate; }
- };
- /// Declaration of a function specialization at template class scope.
- ///
- /// For example:
- /// \code
- /// template <class T>
- /// class A {
- /// template <class U> void foo(U a) { }
- /// template<> void foo(int a) { }
- /// }
- /// \endcode
- ///
- /// "template<> foo(int a)" will be saved in Specialization as a normal
- /// CXXMethodDecl. Then during an instantiation of class A, it will be
- /// transformed into an actual function specialization.
- ///
- /// FIXME: This is redundant; we could store the same information directly on
- /// the CXXMethodDecl as a DependentFunctionTemplateSpecializationInfo.
- class ClassScopeFunctionSpecializationDecl : public Decl {
- CXXMethodDecl *Specialization;
- const ASTTemplateArgumentListInfo *TemplateArgs;
- ClassScopeFunctionSpecializationDecl(
- DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD,
- const ASTTemplateArgumentListInfo *TemplArgs)
- : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc),
- Specialization(FD), TemplateArgs(TemplArgs) {}
- ClassScopeFunctionSpecializationDecl(EmptyShell Empty)
- : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
- virtual void anchor();
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- CXXMethodDecl *getSpecialization() const { return Specialization; }
- bool hasExplicitTemplateArgs() const { return TemplateArgs; }
- const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
- return TemplateArgs;
- }
- static ClassScopeFunctionSpecializationDecl *
- Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD,
- bool HasExplicitTemplateArgs,
- const TemplateArgumentListInfo &TemplateArgs) {
- return new (C, DC) ClassScopeFunctionSpecializationDecl(
- DC, Loc, FD,
- HasExplicitTemplateArgs
- ? ASTTemplateArgumentListInfo::Create(C, TemplateArgs)
- : nullptr);
- }
- static ClassScopeFunctionSpecializationDecl *
- CreateDeserialized(ASTContext &Context, unsigned ID);
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) {
- return K == Decl::ClassScopeFunctionSpecialization;
- }
- };
- /// Represents a variable template specialization, which refers to
- /// a variable template with a given set of template arguments.
- ///
- /// Variable template specializations represent both explicit
- /// specializations of variable templates, as in the example below, and
- /// implicit instantiations of variable templates.
- ///
- /// \code
- /// template<typename T> constexpr T pi = T(3.1415926535897932385);
- ///
- /// template<>
- /// constexpr float pi<float>; // variable template specialization pi<float>
- /// \endcode
- class VarTemplateSpecializationDecl : public VarDecl,
- public llvm::FoldingSetNode {
- /// Structure that stores information about a variable template
- /// specialization that was instantiated from a variable template partial
- /// specialization.
- struct SpecializedPartialSpecialization {
- /// The variable template partial specialization from which this
- /// variable template specialization was instantiated.
- VarTemplatePartialSpecializationDecl *PartialSpecialization;
- /// The template argument list deduced for the variable template
- /// partial specialization itself.
- const TemplateArgumentList *TemplateArgs;
- };
- /// The template that this specialization specializes.
- llvm::PointerUnion<VarTemplateDecl *, SpecializedPartialSpecialization *>
- SpecializedTemplate;
- /// Further info for explicit template specialization/instantiation.
- struct ExplicitSpecializationInfo {
- /// The type-as-written.
- TypeSourceInfo *TypeAsWritten = nullptr;
- /// The location of the extern keyword.
- SourceLocation ExternLoc;
- /// The location of the template keyword.
- SourceLocation TemplateKeywordLoc;
- ExplicitSpecializationInfo() = default;
- };
- /// Further info for explicit template specialization/instantiation.
- /// Does not apply to implicit specializations.
- ExplicitSpecializationInfo *ExplicitInfo = nullptr;
- /// The template arguments used to describe this specialization.
- const TemplateArgumentList *TemplateArgs;
- const ASTTemplateArgumentListInfo *TemplateArgsInfo = nullptr;
- /// The point where this template was instantiated (if any).
- SourceLocation PointOfInstantiation;
- /// The kind of specialization this declaration refers to.
- /// Really a value of type TemplateSpecializationKind.
- unsigned SpecializationKind : 3;
- /// Whether this declaration is a complete definition of the
- /// variable template specialization. We can't otherwise tell apart
- /// an instantiated declaration from an instantiated definition with
- /// no initializer.
- unsigned IsCompleteDefinition : 1;
- protected:
- VarTemplateSpecializationDecl(Kind DK, ASTContext &Context, DeclContext *DC,
- SourceLocation StartLoc, SourceLocation IdLoc,
- VarTemplateDecl *SpecializedTemplate,
- QualType T, TypeSourceInfo *TInfo,
- StorageClass S,
- ArrayRef<TemplateArgument> Args);
- explicit VarTemplateSpecializationDecl(Kind DK, ASTContext &Context);
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- friend class VarDecl;
- static VarTemplateSpecializationDecl *
- Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
- TypeSourceInfo *TInfo, StorageClass S,
- ArrayRef<TemplateArgument> Args);
- static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
- unsigned ID);
- void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
- bool Qualified) const override;
- VarTemplateSpecializationDecl *getMostRecentDecl() {
- VarDecl *Recent = static_cast<VarDecl *>(this)->getMostRecentDecl();
- return cast<VarTemplateSpecializationDecl>(Recent);
- }
- /// Retrieve the template that this specialization specializes.
- VarTemplateDecl *getSpecializedTemplate() const;
- /// Retrieve the template arguments of the variable template
- /// specialization.
- const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; }
- // TODO: Always set this when creating the new specialization?
- void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo);
- void setTemplateArgsInfo(const ASTTemplateArgumentListInfo *ArgsInfo);
- const ASTTemplateArgumentListInfo *getTemplateArgsInfo() const {
- return TemplateArgsInfo;
- }
- /// Determine the kind of specialization that this
- /// declaration represents.
- TemplateSpecializationKind getSpecializationKind() const {
- return static_cast<TemplateSpecializationKind>(SpecializationKind);
- }
- bool isExplicitSpecialization() const {
- return getSpecializationKind() == TSK_ExplicitSpecialization;
- }
- bool isClassScopeExplicitSpecialization() const {
- return isExplicitSpecialization() &&
- isa<CXXRecordDecl>(getLexicalDeclContext());
- }
- /// True if this declaration is an explicit specialization,
- /// explicit instantiation declaration, or explicit instantiation
- /// definition.
- bool isExplicitInstantiationOrSpecialization() const {
- return isTemplateExplicitInstantiationOrSpecialization(
- getTemplateSpecializationKind());
- }
- void setSpecializationKind(TemplateSpecializationKind TSK) {
- SpecializationKind = TSK;
- }
- /// Get the point of instantiation (if any), or null if none.
- SourceLocation getPointOfInstantiation() const {
- return PointOfInstantiation;
- }
- void setPointOfInstantiation(SourceLocation Loc) {
- assert(Loc.isValid() && "point of instantiation must be valid!");
- PointOfInstantiation = Loc;
- }
- void setCompleteDefinition() { IsCompleteDefinition = true; }
- /// If this variable template specialization is an instantiation of
- /// a template (rather than an explicit specialization), return the
- /// variable template or variable template partial specialization from which
- /// it was instantiated.
- llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
- getInstantiatedFrom() const {
- if (!isTemplateInstantiation(getSpecializationKind()))
- return llvm::PointerUnion<VarTemplateDecl *,
- VarTemplatePartialSpecializationDecl *>();
- return getSpecializedTemplateOrPartial();
- }
- /// Retrieve the variable template or variable template partial
- /// specialization which was specialized by this.
- llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
- getSpecializedTemplateOrPartial() const {
- if (const auto *PartialSpec =
- SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
- return PartialSpec->PartialSpecialization;
- return SpecializedTemplate.get<VarTemplateDecl *>();
- }
- /// Retrieve the set of template arguments that should be used
- /// to instantiate the initializer of the variable template or variable
- /// template partial specialization from which this variable template
- /// specialization was instantiated.
- ///
- /// \returns For a variable template specialization instantiated from the
- /// primary template, this function will return the same template arguments
- /// as getTemplateArgs(). For a variable template specialization instantiated
- /// from a variable template partial specialization, this function will the
- /// return deduced template arguments for the variable template partial
- /// specialization itself.
- const TemplateArgumentList &getTemplateInstantiationArgs() const {
- if (const auto *PartialSpec =
- SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
- return *PartialSpec->TemplateArgs;
- return getTemplateArgs();
- }
- /// Note that this variable template specialization is actually an
- /// instantiation of the given variable template partial specialization whose
- /// template arguments have been deduced.
- void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec,
- const TemplateArgumentList *TemplateArgs) {
- assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
- "Already set to a variable template partial specialization!");
- auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
- PS->PartialSpecialization = PartialSpec;
- PS->TemplateArgs = TemplateArgs;
- SpecializedTemplate = PS;
- }
- /// Note that this variable template specialization is an instantiation
- /// of the given variable template.
- void setInstantiationOf(VarTemplateDecl *TemplDecl) {
- assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
- "Previously set to a variable template partial specialization!");
- SpecializedTemplate = TemplDecl;
- }
- /// Sets the type of this specialization as it was written by
- /// the user.
- void setTypeAsWritten(TypeSourceInfo *T) {
- if (!ExplicitInfo)
- ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
- ExplicitInfo->TypeAsWritten = T;
- }
- /// Gets the type of this specialization as it was written by
- /// the user, if it was so written.
- TypeSourceInfo *getTypeAsWritten() const {
- return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
- }
- /// Gets the location of the extern keyword, if present.
- SourceLocation getExternLoc() const {
- return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
- }
- /// Sets the location of the extern keyword.
- void setExternLoc(SourceLocation Loc) {
- if (!ExplicitInfo)
- ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
- ExplicitInfo->ExternLoc = Loc;
- }
- /// Sets the location of the template keyword.
- void setTemplateKeywordLoc(SourceLocation Loc) {
- if (!ExplicitInfo)
- ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
- ExplicitInfo->TemplateKeywordLoc = Loc;
- }
- /// Gets the location of the template keyword, if present.
- SourceLocation getTemplateKeywordLoc() const {
- return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
- }
- SourceRange getSourceRange() const override LLVM_READONLY {
- if (isExplicitSpecialization()) {
- if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsInfo())
- return SourceRange(getOuterLocStart(), Info->getRAngleLoc());
- }
- return VarDecl::getSourceRange();
- }
- void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, TemplateArgs->asArray(), getASTContext());
- }
- static void Profile(llvm::FoldingSetNodeID &ID,
- ArrayRef<TemplateArgument> TemplateArgs,
- ASTContext &Context) {
- ID.AddInteger(TemplateArgs.size());
- for (const TemplateArgument &TemplateArg : TemplateArgs)
- TemplateArg.Profile(ID, Context);
- }
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) {
- return K >= firstVarTemplateSpecialization &&
- K <= lastVarTemplateSpecialization;
- }
- };
- class VarTemplatePartialSpecializationDecl
- : public VarTemplateSpecializationDecl {
- /// The list of template parameters
- TemplateParameterList *TemplateParams = nullptr;
- /// The source info for the template arguments as written.
- /// FIXME: redundant with TypeAsWritten?
- const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
- /// The variable template partial specialization from which this
- /// variable template partial specialization was instantiated.
- ///
- /// The boolean value will be true to indicate that this variable template
- /// partial specialization was specialized at this level.
- llvm::PointerIntPair<VarTemplatePartialSpecializationDecl *, 1, bool>
- InstantiatedFromMember;
- VarTemplatePartialSpecializationDecl(
- ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, TemplateParameterList *Params,
- VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
- StorageClass S, ArrayRef<TemplateArgument> Args,
- const ASTTemplateArgumentListInfo *ArgInfos);
- VarTemplatePartialSpecializationDecl(ASTContext &Context)
- : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization,
- Context),
- InstantiatedFromMember(nullptr, false) {}
- void anchor() override;
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- static VarTemplatePartialSpecializationDecl *
- Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, TemplateParameterList *Params,
- VarTemplateDecl *SpecializedTemplate, QualType T,
- TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args,
- const TemplateArgumentListInfo &ArgInfos);
- static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C,
- unsigned ID);
- VarTemplatePartialSpecializationDecl *getMostRecentDecl() {
- return cast<VarTemplatePartialSpecializationDecl>(
- static_cast<VarTemplateSpecializationDecl *>(
- this)->getMostRecentDecl());
- }
- /// Get the list of template parameters
- TemplateParameterList *getTemplateParameters() const {
- return TemplateParams;
- }
- /// Get the template arguments as written.
- const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
- return ArgsAsWritten;
- }
- /// \brief All associated constraints of this partial specialization,
- /// including the requires clause and any constraints derived from
- /// constrained-parameters.
- ///
- /// The constraints in the resulting list are to be treated as if in a
- /// conjunction ("and").
- void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
- TemplateParams->getAssociatedConstraints(AC);
- }
- bool hasAssociatedConstraints() const {
- return TemplateParams->hasAssociatedConstraints();
- }
- /// \brief Retrieve the member variable template partial specialization from
- /// which this particular variable template partial specialization was
- /// instantiated.
- ///
- /// \code
- /// template<typename T>
- /// struct Outer {
- /// template<typename U> U Inner;
- /// template<typename U> U* Inner<U*> = (U*)(0); // #1
- /// };
- ///
- /// template int* Outer<float>::Inner<int*>;
- /// \endcode
- ///
- /// In this example, the instantiation of \c Outer<float>::Inner<int*> will
- /// end up instantiating the partial specialization
- /// \c Outer<float>::Inner<U*>, which itself was instantiated from the
- /// variable template partial specialization \c Outer<T>::Inner<U*>. Given
- /// \c Outer<float>::Inner<U*>, this function would return
- /// \c Outer<T>::Inner<U*>.
- VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
- const auto *First =
- cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
- return First->InstantiatedFromMember.getPointer();
- }
- void
- setInstantiatedFromMember(VarTemplatePartialSpecializationDecl *PartialSpec) {
- auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
- First->InstantiatedFromMember.setPointer(PartialSpec);
- }
- /// Determines whether this variable template partial specialization
- /// was a specialization of a member partial specialization.
- ///
- /// In the following example, the member template partial specialization
- /// \c X<int>::Inner<T*> is a member specialization.
- ///
- /// \code
- /// template<typename T>
- /// struct X {
- /// template<typename U> U Inner;
- /// template<typename U> U* Inner<U*> = (U*)(0);
- /// };
- ///
- /// template<> template<typename T>
- /// U* X<int>::Inner<T*> = (T*)(0) + 1;
- /// \endcode
- bool isMemberSpecialization() {
- const auto *First =
- cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
- return First->InstantiatedFromMember.getInt();
- }
- /// Note that this member template is a specialization.
- void setMemberSpecialization() {
- auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
- assert(First->InstantiatedFromMember.getPointer() &&
- "Only member templates can be member template specializations");
- return First->InstantiatedFromMember.setInt(true);
- }
- SourceRange getSourceRange() const override LLVM_READONLY {
- if (isExplicitSpecialization()) {
- if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten())
- return SourceRange(getOuterLocStart(), Info->getRAngleLoc());
- }
- return VarDecl::getSourceRange();
- }
- void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(),
- getASTContext());
- }
- static void
- Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
- TemplateParameterList *TPL, ASTContext &Context);
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) {
- return K == VarTemplatePartialSpecialization;
- }
- };
- /// Declaration of a variable template.
- class VarTemplateDecl : public RedeclarableTemplateDecl {
- protected:
- /// Data that is common to all of the declarations of a given
- /// variable template.
- struct Common : CommonBase {
- /// The variable template specializations for this variable
- /// template, including explicit specializations and instantiations.
- llvm::FoldingSetVector<VarTemplateSpecializationDecl> Specializations;
- /// The variable template partial specializations for this variable
- /// template.
- llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>
- PartialSpecializations;
- Common() = default;
- };
- /// Retrieve the set of specializations of this variable template.
- llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
- getSpecializations() const;
- /// Retrieve the set of partial specializations of this class
- /// template.
- llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
- getPartialSpecializations() const;
- VarTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
- DeclarationName Name, TemplateParameterList *Params,
- NamedDecl *Decl)
- : RedeclarableTemplateDecl(VarTemplate, C, DC, L, Name, Params, Decl) {}
- CommonBase *newCommon(ASTContext &C) const override;
- Common *getCommonPtr() const {
- return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
- }
- public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- /// Load any lazily-loaded specializations from the external source.
- void LoadLazySpecializations() const;
- /// Get the underlying variable declarations of the template.
- VarDecl *getTemplatedDecl() const {
- return static_cast<VarDecl *>(TemplatedDecl);
- }
- /// Returns whether this template declaration defines the primary
- /// variable pattern.
- bool isThisDeclarationADefinition() const {
- return getTemplatedDecl()->isThisDeclarationADefinition();
- }
- VarTemplateDecl *getDefinition();
- /// Create a variable template node.
- static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params,
- VarDecl *Decl);
- /// Create an empty variable template node.
- static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- /// Return the specialization with the provided arguments if it exists,
- /// otherwise return the insertion point.
- VarTemplateSpecializationDecl *
- findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos);
- /// Insert the specified specialization knowing that it is not already
- /// in. InsertPos must be obtained from findSpecialization.
- void AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos);
- VarTemplateDecl *getCanonicalDecl() override {
- return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
- }
- const VarTemplateDecl *getCanonicalDecl() const {
- return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
- }
- /// Retrieve the previous declaration of this variable template, or
- /// nullptr if no such declaration exists.
- VarTemplateDecl *getPreviousDecl() {
- return cast_or_null<VarTemplateDecl>(
- static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
- }
- const VarTemplateDecl *getPreviousDecl() const {
- return cast_or_null<VarTemplateDecl>(
- static_cast<const RedeclarableTemplateDecl *>(
- this)->getPreviousDecl());
- }
- VarTemplateDecl *getMostRecentDecl() {
- return cast<VarTemplateDecl>(
- static_cast<RedeclarableTemplateDecl *>(this)->getMostRecentDecl());
- }
- const VarTemplateDecl *getMostRecentDecl() const {
- return const_cast<VarTemplateDecl *>(this)->getMostRecentDecl();
- }
- VarTemplateDecl *getInstantiatedFromMemberTemplate() const {
- return cast_or_null<VarTemplateDecl>(
- RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
- }
- /// Return the partial specialization with the provided arguments if it
- /// exists, otherwise return the insertion point.
- VarTemplatePartialSpecializationDecl *
- findPartialSpecialization(ArrayRef<TemplateArgument> Args,
- TemplateParameterList *TPL, void *&InsertPos);
- /// Insert the specified partial specialization knowing that it is not
- /// already in. InsertPos must be obtained from findPartialSpecialization.
- void AddPartialSpecialization(VarTemplatePartialSpecializationDecl *D,
- void *InsertPos);
- /// Retrieve the partial specializations as an ordered list.
- void getPartialSpecializations(
- SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS) const;
- /// Find a variable template partial specialization which was
- /// instantiated
- /// from the given member partial specialization.
- ///
- /// \param D a member variable template partial specialization.
- ///
- /// \returns the variable template partial specialization which was
- /// instantiated
- /// from the given member partial specialization, or nullptr if no such
- /// partial specialization exists.
- VarTemplatePartialSpecializationDecl *findPartialSpecInstantiatedFromMember(
- VarTemplatePartialSpecializationDecl *D);
- using spec_iterator = SpecIterator<VarTemplateSpecializationDecl>;
- using spec_range = llvm::iterator_range<spec_iterator>;
- spec_range specializations() const {
- return spec_range(spec_begin(), spec_end());
- }
- spec_iterator spec_begin() const {
- return makeSpecIterator(getSpecializations(), false);
- }
- spec_iterator spec_end() const {
- return makeSpecIterator(getSpecializations(), true);
- }
- // Implement isa/cast/dyncast support
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == VarTemplate; }
- };
- /// Declaration of a C++20 concept.
- class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> {
- protected:
- Expr *ConstraintExpr;
- ConceptDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, Expr *ConstraintExpr)
- : TemplateDecl(Concept, DC, L, Name, Params),
- ConstraintExpr(ConstraintExpr) {};
- public:
- static ConceptDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params,
- Expr *ConstraintExpr);
- static ConceptDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- Expr *getConstraintExpr() const {
- return ConstraintExpr;
- }
- SourceRange getSourceRange() const override LLVM_READONLY {
- return SourceRange(getTemplateParameters()->getTemplateLoc(),
- ConstraintExpr->getEndLoc());
- }
- bool isTypeConcept() const {
- return isa<TemplateTypeParmDecl>(getTemplateParameters()->getParam(0));
- }
- ConceptDecl *getCanonicalDecl() override {
- return cast<ConceptDecl>(getPrimaryMergedDecl(this));
- }
- const ConceptDecl *getCanonicalDecl() const {
- return const_cast<ConceptDecl *>(this)->getCanonicalDecl();
- }
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == Concept; }
- friend class ASTReader;
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
- };
- // An implementation detail of ConceptSpecialicationExpr that holds the template
- // arguments, so we can later use this to reconstitute the template arguments
- // during constraint checking.
- class ImplicitConceptSpecializationDecl final
- : public Decl,
- private llvm::TrailingObjects<ImplicitConceptSpecializationDecl,
- TemplateArgument> {
- unsigned NumTemplateArgs;
- ImplicitConceptSpecializationDecl(DeclContext *DC, SourceLocation SL,
- ArrayRef<TemplateArgument> ConvertedArgs);
- ImplicitConceptSpecializationDecl(EmptyShell Empty, unsigned NumTemplateArgs);
- public:
- static ImplicitConceptSpecializationDecl *
- Create(const ASTContext &C, DeclContext *DC, SourceLocation SL,
- ArrayRef<TemplateArgument> ConvertedArgs);
- static ImplicitConceptSpecializationDecl *
- CreateDeserialized(const ASTContext &C, unsigned ID,
- unsigned NumTemplateArgs);
- ArrayRef<TemplateArgument> getTemplateArguments() const {
- return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
- NumTemplateArgs);
- }
- void setTemplateArguments(ArrayRef<TemplateArgument> Converted);
- static bool classofKind(Kind K) { return K == ImplicitConceptSpecialization; }
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- friend TrailingObjects;
- friend class ASTDeclReader;
- };
- /// A template parameter object.
- ///
- /// Template parameter objects represent values of class type used as template
- /// arguments. There is one template parameter object for each such distinct
- /// value used as a template argument across the program.
- ///
- /// \code
- /// struct A { int x, y; };
- /// template<A> struct S;
- /// S<A{1, 2}> s1;
- /// S<A{1, 2}> s2; // same type, argument is same TemplateParamObjectDecl.
- /// \endcode
- class TemplateParamObjectDecl : public ValueDecl,
- public Mergeable<TemplateParamObjectDecl>,
- public llvm::FoldingSetNode {
- private:
- /// The value of this template parameter object.
- APValue Value;
- TemplateParamObjectDecl(DeclContext *DC, QualType T, const APValue &V)
- : ValueDecl(TemplateParamObject, DC, SourceLocation(), DeclarationName(),
- T),
- Value(V) {}
- static TemplateParamObjectDecl *Create(const ASTContext &C, QualType T,
- const APValue &V);
- static TemplateParamObjectDecl *CreateDeserialized(ASTContext &C,
- unsigned ID);
- /// Only ASTContext::getTemplateParamObjectDecl and deserialization
- /// create these.
- friend class ASTContext;
- friend class ASTReader;
- friend class ASTDeclReader;
- public:
- /// Print this template parameter object in a human-readable format.
- void printName(llvm::raw_ostream &OS,
- const PrintingPolicy &Policy) const override;
- /// Print this object as an equivalent expression.
- void printAsExpr(llvm::raw_ostream &OS) const;
- void printAsExpr(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
- /// Print this object as an initializer suitable for a variable of the
- /// object's type.
- void printAsInit(llvm::raw_ostream &OS) const;
- void printAsInit(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
- const APValue &getValue() const { return Value; }
- static void Profile(llvm::FoldingSetNodeID &ID, QualType T,
- const APValue &V) {
- ID.AddPointer(T.getCanonicalType().getAsOpaquePtr());
- V.Profile(ID);
- }
- void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getType(), getValue());
- }
- TemplateParamObjectDecl *getCanonicalDecl() override {
- return getFirstDecl();
- }
- const TemplateParamObjectDecl *getCanonicalDecl() const {
- return getFirstDecl();
- }
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == TemplateParamObject; }
- };
- inline NamedDecl *getAsNamedDecl(TemplateParameter P) {
- if (auto *PD = P.dyn_cast<TemplateTypeParmDecl *>())
- return PD;
- if (auto *PD = P.dyn_cast<NonTypeTemplateParmDecl *>())
- return PD;
- return P.get<TemplateTemplateParmDecl *>();
- }
- inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) {
- auto *TD = dyn_cast<TemplateDecl>(D);
- return TD && (isa<ClassTemplateDecl>(TD) ||
- isa<ClassTemplatePartialSpecializationDecl>(TD) ||
- isa<TypeAliasTemplateDecl>(TD) ||
- isa<TemplateTemplateParmDecl>(TD))
- ? TD
- : nullptr;
- }
- /// Check whether the template parameter is a pack expansion, and if so,
- /// determine the number of parameters produced by that expansion. For instance:
- ///
- /// \code
- /// template<typename ...Ts> struct A {
- /// template<Ts ...NTs, template<Ts> class ...TTs, typename ...Us> struct B;
- /// };
- /// \endcode
- ///
- /// In \c A<int,int>::B, \c NTs and \c TTs have expanded pack size 2, and \c Us
- /// is not a pack expansion, so returns an empty Optional.
- inline std::optional<unsigned> getExpandedPackSize(const NamedDecl *Param) {
- if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
- if (TTP->isExpandedParameterPack())
- return TTP->getNumExpansionParameters();
- }
- if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- if (NTTP->isExpandedParameterPack())
- return NTTP->getNumExpansionTypes();
- }
- if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param)) {
- if (TTP->isExpandedParameterPack())
- return TTP->getNumExpansionTemplateParameters();
- }
- return std::nullopt;
- }
- /// Internal helper used by Subst* nodes to retrieve the parameter list
- /// for their AssociatedDecl.
- TemplateParameterList *getReplacedTemplateParameterList(Decl *D);
- } // namespace clang
- #endif // LLVM_CLANG_AST_DECLTEMPLATE_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|