12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404 |
- #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/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 <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::makeArrayRef(begin(), end());
- }
- ArrayRef<const NamedDecl*> asArray() const {
- return llvm::makeArrayRef(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 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::makeArrayRef(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) {
- assert(!isInherited() && "default argument already inherited");
- InheritedFrom = getParmOwningDefaultArg(InheritedFrom);
- if (!isSet())
- ValueOrInherited = 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; }
- // 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;
- void setTemplateParameters(TemplateParameterList *TParams) {
- TemplateParams = TParams;
- }
- public:
- /// Initialize the underlying templated declaration and
- /// template parameters.
- void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
- assert(!TemplatedDecl && "TemplatedDecl already set!");
- assert(!TemplateParams && "TemplateParams already set!");
- TemplatedDecl = templatedDecl;
- TemplateParams = templateParams;
- }
- };
- /// 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::makeArrayRef(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;
- };
- /// 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);
- }
- 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;
- /// The set of "injected" template arguments used within this
- /// function template.
- ///
- /// This pointer refers to the template arguments (there are as
- /// many template arguments as template parameaters) for the function
- /// template, and is allocated lazily, since most function templates do not
- /// require the use of this information.
- TemplateArgument *InjectedArgs = nullptr;
- 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);
- }
- /// Retrieve the "injected" template arguments that correspond to the
- /// template parameters of this function template.
- ///
- /// Although the C++ standard has no notion of the "injected" template
- /// arguments for a function template, the notion is convenient when
- /// we need to perform substitutions inside the definition of a function
- /// template.
- ArrayRef<TemplateArgument> getInjectedTemplateArgs();
- /// 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 paramter 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:
- // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for
- // position? Maybe?
- unsigned Depth;
- unsigned Position;
- TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) {}
- public:
- TemplateParmPosition() = delete;
- /// Get the nesting depth of the template parameter.
- unsigned getDepth() const { return Depth; }
- void setDepth(unsigned D) { Depth = D; }
- /// Get the position of the template parameter within its parameter list.
- unsigned getPosition() const { return Position; }
- void setPosition(unsigned P) { 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 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 : 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, Optional<unsigned> NumExpanded)
- : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename),
- HasTypeConstraint(HasTypeConstraint), TypeConstraintInitialized(false),
- ExpandedParameterPack(NumExpanded),
- NumExpanded(NumExpanded.getValueOr(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,
- Optional<unsigned> NumExpanded = None);
- 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 getConstraintExpression 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;
- TemplateArgumentListInfo TemplateArgsInfo;
- /// 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);
- const TemplateArgumentListInfo &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();
- }
- 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);
- }
- 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++2a 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 getFirstDecl(); }
- const ConceptDecl *getCanonicalDecl() const { return getFirstDecl(); }
- // 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;
- };
- /// 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 override;
- /// Print this object as an equivalent expression.
- void printAsExpr(llvm::raw_ostream &OS) const;
- /// Print this object as an initializer suitable for a variable of the
- /// object's type.
- void printAsInit(llvm::raw_ostream &OS) 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 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 None;
- }
- } // namespace clang
- #endif // LLVM_CLANG_AST_DECLTEMPLATE_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|