Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:01

0001 //===--- ParsedTemplate.h - Template Parsing Data Types ---------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file provides data structures that store the parsed representation of
0010 //  templates.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
0015 #define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
0016 
0017 #include "clang/Basic/OperatorKinds.h"
0018 #include "clang/Basic/SourceLocation.h"
0019 #include "clang/Basic/TemplateKinds.h"
0020 #include "clang/Sema/DeclSpec.h"
0021 #include "clang/Sema/Ownership.h"
0022 #include "llvm/ADT/SmallVector.h"
0023 #include <cassert>
0024 #include <cstdlib>
0025 #include <new>
0026 
0027 namespace clang {
0028   /// Represents the parsed form of a C++ template argument.
0029   class ParsedTemplateArgument {
0030   public:
0031     /// Describes the kind of template argument that was parsed.
0032     enum KindType {
0033       /// A template type parameter, stored as a type.
0034       Type,
0035       /// A non-type template parameter, stored as an expression.
0036       NonType,
0037       /// A template template argument, stored as a template name.
0038       Template
0039     };
0040 
0041     /// Build an empty template argument.
0042     ///
0043     /// This template argument is invalid.
0044     ParsedTemplateArgument() : Kind(Type), Arg(nullptr) { }
0045 
0046     /// Create a template type argument or non-type template argument.
0047     ///
0048     /// \param Arg the template type argument or non-type template argument.
0049     /// \param Loc the location of the type.
0050     ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
0051       : Kind(Kind), Arg(Arg), Loc(Loc) { }
0052 
0053     /// Create a template template argument.
0054     ///
0055     /// \param SS the C++ scope specifier that precedes the template name, if
0056     /// any.
0057     ///
0058     /// \param Template the template to which this template template
0059     /// argument refers.
0060     ///
0061     /// \param TemplateLoc the location of the template name.
0062     ParsedTemplateArgument(const CXXScopeSpec &SS,
0063                            ParsedTemplateTy Template,
0064                            SourceLocation TemplateLoc)
0065       : Kind(ParsedTemplateArgument::Template),
0066         Arg(Template.getAsOpaquePtr()), SS(SS), Loc(TemplateLoc) {}
0067 
0068     /// Determine whether the given template argument is invalid.
0069     bool isInvalid() const { return Arg == nullptr; }
0070 
0071     /// Determine what kind of template argument we have.
0072     KindType getKind() const { return Kind; }
0073 
0074     /// Retrieve the template type argument's type.
0075     ParsedType getAsType() const {
0076       assert(Kind == Type && "Not a template type argument");
0077       return ParsedType::getFromOpaquePtr(Arg);
0078     }
0079 
0080     /// Retrieve the non-type template argument's expression.
0081     Expr *getAsExpr() const {
0082       assert(Kind == NonType && "Not a non-type template argument");
0083       return static_cast<Expr*>(Arg);
0084     }
0085 
0086     /// Retrieve the template template argument's template name.
0087     ParsedTemplateTy getAsTemplate() const {
0088       assert(Kind == Template && "Not a template template argument");
0089       return ParsedTemplateTy::getFromOpaquePtr(Arg);
0090     }
0091 
0092     /// Retrieve the location of the template argument.
0093     SourceLocation getLocation() const { return Loc; }
0094 
0095     /// Retrieve the nested-name-specifier that precedes the template
0096     /// name in a template template argument.
0097     const CXXScopeSpec &getScopeSpec() const {
0098       assert(Kind == Template &&
0099              "Only template template arguments can have a scope specifier");
0100       return SS;
0101     }
0102 
0103     /// Retrieve the location of the ellipsis that makes a template
0104     /// template argument into a pack expansion.
0105     SourceLocation getEllipsisLoc() const {
0106       assert(Kind == Template &&
0107              "Only template template arguments can have an ellipsis");
0108       return EllipsisLoc;
0109     }
0110 
0111     /// Retrieve a pack expansion of the given template template
0112     /// argument.
0113     ///
0114     /// \param EllipsisLoc The location of the ellipsis.
0115     ParsedTemplateArgument getTemplatePackExpansion(
0116                                               SourceLocation EllipsisLoc) const;
0117 
0118   private:
0119     KindType Kind;
0120 
0121     /// The actual template argument representation, which may be
0122     /// an \c Sema::TypeTy* (for a type), an Expr* (for an
0123     /// expression), or an Sema::TemplateTy (for a template).
0124     void *Arg;
0125 
0126     /// The nested-name-specifier that can accompany a template template
0127     /// argument.
0128     CXXScopeSpec SS;
0129 
0130     /// the location of the template argument.
0131     SourceLocation Loc;
0132 
0133     /// The ellipsis location that can accompany a template template
0134     /// argument (turning it into a template template argument expansion).
0135     SourceLocation EllipsisLoc;
0136   };
0137 
0138   /// Information about a template-id annotation
0139   /// token.
0140   ///
0141   /// A template-id annotation token contains the template name,
0142   /// template arguments, and the source locations for important
0143   /// tokens. All of the information about template arguments is allocated
0144   /// directly after this structure.
0145   /// A template-id annotation token can also be generated by a type-constraint
0146   /// construct with no explicit template arguments, e.g. "template<C T>" would
0147   /// annotate C as a TemplateIdAnnotation with no template arguments (the angle
0148   /// locations would be invalid in this case).
0149   struct TemplateIdAnnotation final
0150       : private llvm::TrailingObjects<TemplateIdAnnotation,
0151                                       ParsedTemplateArgument> {
0152     friend TrailingObjects;
0153     /// TemplateKWLoc - The location of the template keyword.
0154     /// For e.g. typename T::template Y<U>
0155     SourceLocation TemplateKWLoc;
0156 
0157     /// TemplateNameLoc - The location of the template name within the
0158     /// source.
0159     SourceLocation TemplateNameLoc;
0160 
0161     /// FIXME: Temporarily stores the name of a specialization
0162     const IdentifierInfo *Name;
0163 
0164     /// FIXME: Temporarily stores the overloaded operator kind.
0165     OverloadedOperatorKind Operator;
0166 
0167     /// The declaration of the template corresponding to the
0168     /// template-name.
0169     ParsedTemplateTy Template;
0170 
0171     /// The kind of template that Template refers to. If this is
0172     /// TNK_Non_template, an error was encountered and diagnosed
0173     /// when parsing or looking up the template name.
0174     TemplateNameKind Kind;
0175 
0176     /// The location of the '<' before the template argument
0177     /// list.
0178     SourceLocation LAngleLoc;
0179 
0180     /// The location of the '>' after the template argument
0181     /// list.
0182     SourceLocation RAngleLoc;
0183 
0184     /// NumArgs - The number of template arguments.
0185     unsigned NumArgs;
0186 
0187     /// Whether an error was encountered in the template arguments.
0188     /// If so, NumArgs and the trailing arguments are best-effort.
0189     bool ArgsInvalid;
0190 
0191     /// Retrieves a pointer to the template arguments
0192     ParsedTemplateArgument *getTemplateArgs() {
0193       return getTrailingObjects<ParsedTemplateArgument>();
0194     }
0195 
0196     /// Creates a new TemplateIdAnnotation with NumArgs arguments and
0197     /// appends it to List.
0198     static TemplateIdAnnotation *
0199     Create(SourceLocation TemplateKWLoc, SourceLocation TemplateNameLoc,
0200            const IdentifierInfo *Name, OverloadedOperatorKind OperatorKind,
0201            ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind,
0202            SourceLocation LAngleLoc, SourceLocation RAngleLoc,
0203            ArrayRef<ParsedTemplateArgument> TemplateArgs, bool ArgsInvalid,
0204            SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) {
0205       TemplateIdAnnotation *TemplateId = new (llvm::safe_malloc(
0206           totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size())))
0207           TemplateIdAnnotation(TemplateKWLoc, TemplateNameLoc, Name,
0208                                OperatorKind, OpaqueTemplateName, TemplateKind,
0209                                LAngleLoc, RAngleLoc, TemplateArgs, ArgsInvalid);
0210       CleanupList.push_back(TemplateId);
0211       return TemplateId;
0212     }
0213 
0214     void Destroy() {
0215       for (ParsedTemplateArgument &A :
0216            llvm::make_range(getTemplateArgs(), getTemplateArgs() + NumArgs))
0217         A.~ParsedTemplateArgument();
0218       this->~TemplateIdAnnotation();
0219       free(this);
0220     }
0221 
0222     /// Determine whether this might be a type template.
0223     bool mightBeType() const {
0224       return Kind == TNK_Non_template ||
0225              Kind == TNK_Type_template ||
0226              Kind == TNK_Dependent_template_name ||
0227              Kind == TNK_Undeclared_template;
0228     }
0229 
0230     bool hasInvalidName() const { return Kind == TNK_Non_template; }
0231     bool hasInvalidArgs() const { return ArgsInvalid; }
0232 
0233     bool isInvalid() const { return hasInvalidName() || hasInvalidArgs(); }
0234 
0235   private:
0236     TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
0237 
0238     TemplateIdAnnotation(SourceLocation TemplateKWLoc,
0239                          SourceLocation TemplateNameLoc,
0240                          const IdentifierInfo *Name,
0241                          OverloadedOperatorKind OperatorKind,
0242                          ParsedTemplateTy OpaqueTemplateName,
0243                          TemplateNameKind TemplateKind,
0244                          SourceLocation LAngleLoc, SourceLocation RAngleLoc,
0245                          ArrayRef<ParsedTemplateArgument> TemplateArgs,
0246                          bool ArgsInvalid) noexcept
0247         : TemplateKWLoc(TemplateKWLoc), TemplateNameLoc(TemplateNameLoc),
0248           Name(Name), Operator(OperatorKind), Template(OpaqueTemplateName),
0249           Kind(TemplateKind), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
0250           NumArgs(TemplateArgs.size()), ArgsInvalid(ArgsInvalid) {
0251 
0252       std::uninitialized_copy(TemplateArgs.begin(), TemplateArgs.end(),
0253                               getTemplateArgs());
0254     }
0255     ~TemplateIdAnnotation() = default;
0256   };
0257 
0258   /// Retrieves the range of the given template parameter lists.
0259   SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
0260                                      unsigned NumParams);
0261 } // end namespace clang
0262 
0263 #endif // LLVM_CLANG_SEMA_PARSEDTEMPLATE_H