diff options
Diffstat (limited to 'include/clang/AST/TemplateBase.h')
-rw-r--r-- | include/clang/AST/TemplateBase.h | 101 |
1 files changed, 28 insertions, 73 deletions
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 65f5460..54c9f2c 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -73,7 +73,15 @@ private: union { uintptr_t TypeOrValue; struct { - char Value[sizeof(llvm::APSInt)]; + // We store a decomposed APSInt with the data allocated by ASTContext if + // BitWidth > 64. The memory may be shared between multiple + // TemplateArgument instances. + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + unsigned BitWidth : 31; + unsigned IsUnsigned : 1; void *Type; } Integer; struct { @@ -104,11 +112,15 @@ public: TypeOrValue = reinterpret_cast<uintptr_t>(D); } - /// \brief Construct an integral constant template argument. - TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { - // FIXME: Large integral values will get leaked. Do something - // similar to what we did with IntegerLiteral. - new (Integer.Value) llvm::APSInt(Value); + /// \brief Construct an integral constant template argument. The memory to + /// store the value is allocated with Ctx. + TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type); + + /// \brief Construct an integral constant template argument with the same + /// value as Other but a different type. + TemplateArgument(const TemplateArgument &Other, QualType Type) + : Kind(Integral) { + Integer = Other.Integer; Integer.Type = Type.getAsOpaquePtr(); } @@ -165,62 +177,6 @@ public: this->Args.NumArgs = NumArgs; } - /// \brief Copy constructor for a template argument. - TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { - // FIXME: Large integral values will get leaked. Do something - // similar to what we did with IntegerLiteral. - if (Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else if (Kind == Pack) { - Args.NumArgs = Other.Args.NumArgs; - Args.Args = Other.Args.Args; - } else if (Kind == Template || Kind == TemplateExpansion) { - TemplateArg.Name = Other.TemplateArg.Name; - TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; - } else - TypeOrValue = Other.TypeOrValue; - } - - TemplateArgument& operator=(const TemplateArgument& Other) { - using llvm::APSInt; - - if (Kind == Other.Kind && Kind == Integral) { - // Copy integral values. - *this->getAsIntegral() = *Other.getAsIntegral(); - Integer.Type = Other.Integer.Type; - return *this; - } - - // Destroy the current integral value, if that's what we're holding. - if (Kind == Integral) - getAsIntegral()->~APSInt(); - - Kind = Other.Kind; - - if (Other.Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else if (Other.Kind == Pack) { - Args.NumArgs = Other.Args.NumArgs; - Args.Args = Other.Args.Args; - } else if (Kind == Template || Kind == TemplateExpansion) { - TemplateArg.Name = Other.TemplateArg.Name; - TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; - } else { - TypeOrValue = Other.TypeOrValue; - } - - return *this; - } - - ~TemplateArgument() { - using llvm::APSInt; - - if (Kind == Integral) - getAsIntegral()->~APSInt(); - } - /// \brief Create a new template argument pack by copying the given set of /// template arguments. static TemplateArgument CreatePackCopy(ASTContext &Context, @@ -286,14 +242,15 @@ public: llvm::Optional<unsigned> getNumTemplateExpansions() const; /// \brief Retrieve the template argument as an integral value. - llvm::APSInt *getAsIntegral() { - if (Kind != Integral) - return 0; - return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); - } + // FIXME: Provide a way to read the integral data without copying the value. + llvm::APSInt getAsIntegral() const { + using namespace llvm; + if (Integer.BitWidth <= 64) + return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); - const llvm::APSInt *getAsIntegral() const { - return const_cast<TemplateArgument*>(this)->getAsIntegral(); + unsigned NumWords = APInt::getNumWords(Integer.BitWidth); + return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)), + Integer.IsUnsigned); } /// \brief Retrieve the type of the integral value. @@ -342,14 +299,12 @@ public: return Args.NumArgs; } - /// Determines whether two template arguments are superficially the + /// \brief Determines whether two template arguments are superficially the /// same. bool structurallyEquals(const TemplateArgument &Other) const; - /// \brief When the template argument is a pack expansion, returns + /// \brief When the template argument is a pack expansion, returns /// the pattern of the pack expansion. - /// - /// \param Ellipsis Will be set to the location of the ellipsis. TemplateArgument getPackExpansionPattern() const; /// \brief Print this template argument to the given output stream. |