diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang16/include/clang/AST/ExprCXX.h | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/clang16/include/clang/AST/ExprCXX.h')
-rw-r--r-- | contrib/libs/clang16/include/clang/AST/ExprCXX.h | 5152 |
1 files changed, 5152 insertions, 0 deletions
diff --git a/contrib/libs/clang16/include/clang/AST/ExprCXX.h b/contrib/libs/clang16/include/clang/AST/ExprCXX.h new file mode 100644 index 0000000000..77b88f022e --- /dev/null +++ b/contrib/libs/clang16/include/clang/AST/ExprCXX.h @@ -0,0 +1,5152 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ExprCXX.h - Classes for representing expressions ---------*- 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 clang::Expr interface and subclasses for C++ expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPRCXX_H +#define LLVM_CLANG_AST_EXPRCXX_H + +#include "clang/AST/ASTConcept.h" +#include "clang/AST/ComputeDependence.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/DependenceFlags.h" +#include "clang/AST/Expr.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" +#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/ExceptionSpecificationType.h" +#include "clang/Basic/ExpressionTraits.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Lambda.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TypeTraits.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.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 <memory> +#include <optional> + +namespace clang { + +class ASTContext; +class DeclAccessPair; +class IdentifierInfo; +class LambdaCapture; +class NonTypeTemplateParmDecl; +class TemplateParameterList; + +//===--------------------------------------------------------------------===// +// C++ Expressions. +//===--------------------------------------------------------------------===// + +/// A call to an overloaded operator written using operator +/// syntax. +/// +/// Represents a call to an overloaded operator written using operator +/// syntax, e.g., "x + y" or "*p". While semantically equivalent to a +/// normal call, this AST node provides better information about the +/// syntactic representation of the call. +/// +/// In a C++ template, this expression node kind will be used whenever +/// any of the arguments are type-dependent. In this case, the +/// function itself will be a (possibly empty) set of functions and +/// function templates that were found by name lookup at template +/// definition time. +class CXXOperatorCallExpr final : public CallExpr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + + SourceRange Range; + + // CXXOperatorCallExpr has some trailing objects belonging + // to CallExpr. See CallExpr for the details. + + SourceRange getSourceRangeImpl() const LLVM_READONLY; + + CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation OperatorLoc, FPOptionsOverride FPFeatures, + ADLCallKind UsesADL); + + CXXOperatorCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); + +public: + static CXXOperatorCallExpr * + Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation OperatorLoc, FPOptionsOverride FPFeatures, + ADLCallKind UsesADL = NotADL); + + static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, bool HasFPFeatures, + EmptyShell Empty); + + /// Returns the kind of overloaded operator that this expression refers to. + OverloadedOperatorKind getOperator() const { + return static_cast<OverloadedOperatorKind>( + CXXOperatorCallExprBits.OperatorKind); + } + + static bool isAssignmentOp(OverloadedOperatorKind Opc) { + return Opc == OO_Equal || Opc == OO_StarEqual || Opc == OO_SlashEqual || + Opc == OO_PercentEqual || Opc == OO_PlusEqual || + Opc == OO_MinusEqual || Opc == OO_LessLessEqual || + Opc == OO_GreaterGreaterEqual || Opc == OO_AmpEqual || + Opc == OO_CaretEqual || Opc == OO_PipeEqual; + } + bool isAssignmentOp() const { return isAssignmentOp(getOperator()); } + + static bool isComparisonOp(OverloadedOperatorKind Opc) { + switch (Opc) { + case OO_EqualEqual: + case OO_ExclaimEqual: + case OO_Greater: + case OO_GreaterEqual: + case OO_Less: + case OO_LessEqual: + case OO_Spaceship: + return true; + default: + return false; + } + } + bool isComparisonOp() const { return isComparisonOp(getOperator()); } + + /// Is this written as an infix binary operator? + bool isInfixBinaryOp() const; + + /// Returns the location of the operator symbol in the expression. + /// + /// When \c getOperator()==OO_Call, this is the location of the right + /// parentheses; when \c getOperator()==OO_Subscript, this is the location + /// of the right bracket. + SourceLocation getOperatorLoc() const { return getRParenLoc(); } + + SourceLocation getExprLoc() const LLVM_READONLY { + OverloadedOperatorKind Operator = getOperator(); + return (Operator < OO_Plus || Operator >= OO_Arrow || + Operator == OO_PlusPlus || Operator == OO_MinusMinus) + ? getBeginLoc() + : getOperatorLoc(); + } + + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } + SourceRange getSourceRange() const { return Range; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXOperatorCallExprClass; + } +}; + +/// Represents a call to a member function that +/// may be written either with member call syntax (e.g., "obj.func()" +/// or "objptr->func()") or with normal function-call syntax +/// ("func()") within a member function that ends up calling a member +/// function. The callee in either case is a MemberExpr that contains +/// both the object argument and the member function, while the +/// arguments are the arguments within the parentheses (not including +/// the object argument). +class CXXMemberCallExpr final : public CallExpr { + // CXXMemberCallExpr has some trailing objects belonging + // to CallExpr. See CallExpr for the details. + + CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation RP, + FPOptionsOverride FPOptions, unsigned MinNumArgs); + + CXXMemberCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); + +public: + static CXXMemberCallExpr *Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation RP, + FPOptionsOverride FPFeatures, + unsigned MinNumArgs = 0); + + static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, + bool HasFPFeatures, EmptyShell Empty); + + /// Retrieve the implicit object argument for the member call. + /// + /// For example, in "x.f(5)", this returns the sub-expression "x". + Expr *getImplicitObjectArgument() const; + + /// Retrieve the type of the object argument. + /// + /// Note that this always returns a non-pointer type. + QualType getObjectType() const; + + /// Retrieve the declaration of the called method. + CXXMethodDecl *getMethodDecl() const; + + /// Retrieve the CXXRecordDecl for the underlying type of + /// the implicit object argument. + /// + /// Note that this is may not be the same declaration as that of the class + /// context of the CXXMethodDecl which this function is calling. + /// FIXME: Returns 0 for member pointer call exprs. + CXXRecordDecl *getRecordDecl() const; + + SourceLocation getExprLoc() const LLVM_READONLY { + SourceLocation CLoc = getCallee()->getExprLoc(); + if (CLoc.isValid()) + return CLoc; + + return getBeginLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXMemberCallExprClass; + } +}; + +/// Represents a call to a CUDA kernel function. +class CUDAKernelCallExpr final : public CallExpr { + friend class ASTStmtReader; + + enum { CONFIG, END_PREARG }; + + // CUDAKernelCallExpr has some trailing objects belonging + // to CallExpr. See CallExpr for the details. + + CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef<Expr *> Args, + QualType Ty, ExprValueKind VK, SourceLocation RP, + FPOptionsOverride FPFeatures, unsigned MinNumArgs); + + CUDAKernelCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); + +public: + static CUDAKernelCallExpr *Create(const ASTContext &Ctx, Expr *Fn, + CallExpr *Config, ArrayRef<Expr *> Args, + QualType Ty, ExprValueKind VK, + SourceLocation RP, + FPOptionsOverride FPFeatures, + unsigned MinNumArgs = 0); + + static CUDAKernelCallExpr *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, bool HasFPFeatures, + EmptyShell Empty); + + const CallExpr *getConfig() const { + return cast_or_null<CallExpr>(getPreArg(CONFIG)); + } + CallExpr *getConfig() { return cast_or_null<CallExpr>(getPreArg(CONFIG)); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CUDAKernelCallExprClass; + } +}; + +/// A rewritten comparison expression that was originally written using +/// operator syntax. +/// +/// In C++20, the following rewrites are performed: +/// - <tt>a == b</tt> -> <tt>b == a</tt> +/// - <tt>a != b</tt> -> <tt>!(a == b)</tt> +/// - <tt>a != b</tt> -> <tt>!(b == a)</tt> +/// - For \c \@ in \c <, \c <=, \c >, \c >=, \c <=>: +/// - <tt>a @ b</tt> -> <tt>(a <=> b) @ 0</tt> +/// - <tt>a @ b</tt> -> <tt>0 @ (b <=> a)</tt> +/// +/// This expression provides access to both the original syntax and the +/// rewritten expression. +/// +/// Note that the rewritten calls to \c ==, \c <=>, and \c \@ are typically +/// \c CXXOperatorCallExprs, but could theoretically be \c BinaryOperators. +class CXXRewrittenBinaryOperator : public Expr { + friend class ASTStmtReader; + + /// The rewritten semantic form. + Stmt *SemanticForm; + +public: + CXXRewrittenBinaryOperator(Expr *SemanticForm, bool IsReversed) + : Expr(CXXRewrittenBinaryOperatorClass, SemanticForm->getType(), + SemanticForm->getValueKind(), SemanticForm->getObjectKind()), + SemanticForm(SemanticForm) { + CXXRewrittenBinaryOperatorBits.IsReversed = IsReversed; + setDependence(computeDependence(this)); + } + CXXRewrittenBinaryOperator(EmptyShell Empty) + : Expr(CXXRewrittenBinaryOperatorClass, Empty), SemanticForm() {} + + /// Get an equivalent semantic form for this expression. + Expr *getSemanticForm() { return cast<Expr>(SemanticForm); } + const Expr *getSemanticForm() const { return cast<Expr>(SemanticForm); } + + struct DecomposedForm { + /// The original opcode, prior to rewriting. + BinaryOperatorKind Opcode; + /// The original left-hand side. + const Expr *LHS; + /// The original right-hand side. + const Expr *RHS; + /// The inner \c == or \c <=> operator expression. + const Expr *InnerBinOp; + }; + + /// Decompose this operator into its syntactic form. + DecomposedForm getDecomposedForm() const LLVM_READONLY; + + /// Determine whether this expression was rewritten in reverse form. + bool isReversed() const { return CXXRewrittenBinaryOperatorBits.IsReversed; } + + BinaryOperatorKind getOperator() const { return getDecomposedForm().Opcode; } + BinaryOperatorKind getOpcode() const { return getOperator(); } + static StringRef getOpcodeStr(BinaryOperatorKind Op) { + return BinaryOperator::getOpcodeStr(Op); + } + StringRef getOpcodeStr() const { + return BinaryOperator::getOpcodeStr(getOpcode()); + } + bool isComparisonOp() const { return true; } + bool isAssignmentOp() const { return false; } + + const Expr *getLHS() const { return getDecomposedForm().LHS; } + const Expr *getRHS() const { return getDecomposedForm().RHS; } + + SourceLocation getOperatorLoc() const LLVM_READONLY { + return getDecomposedForm().InnerBinOp->getExprLoc(); + } + SourceLocation getExprLoc() const LLVM_READONLY { return getOperatorLoc(); } + + /// Compute the begin and end locations from the decomposed form. + /// The locations of the semantic form are not reliable if this is + /// a reversed expression. + //@{ + SourceLocation getBeginLoc() const LLVM_READONLY { + return getDecomposedForm().LHS->getBeginLoc(); + } + SourceLocation getEndLoc() const LLVM_READONLY { + return getDecomposedForm().RHS->getEndLoc(); + } + SourceRange getSourceRange() const LLVM_READONLY { + DecomposedForm DF = getDecomposedForm(); + return SourceRange(DF.LHS->getBeginLoc(), DF.RHS->getEndLoc()); + } + //@} + + child_range children() { + return child_range(&SemanticForm, &SemanticForm + 1); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXRewrittenBinaryOperatorClass; + } +}; + +/// Abstract class common to all of the C++ "named"/"keyword" casts. +/// +/// This abstract class is inherited by all of the classes +/// representing "named" casts: CXXStaticCastExpr for \c static_cast, +/// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for +/// reinterpret_cast, CXXConstCastExpr for \c const_cast and +/// CXXAddrspaceCastExpr for addrspace_cast (in OpenCL). +class CXXNamedCastExpr : public ExplicitCastExpr { +private: + // the location of the casting op + SourceLocation Loc; + + // the location of the right parenthesis + SourceLocation RParenLoc; + + // range for '<' '>' + SourceRange AngleBrackets; + +protected: + friend class ASTStmtReader; + + CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK, CastKind kind, + Expr *op, unsigned PathSize, bool HasFPFeatures, + TypeSourceInfo *writtenTy, SourceLocation l, + SourceLocation RParenLoc, SourceRange AngleBrackets) + : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, HasFPFeatures, + writtenTy), + Loc(l), RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {} + + explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize, + bool HasFPFeatures) + : ExplicitCastExpr(SC, Shell, PathSize, HasFPFeatures) {} + +public: + const char *getCastName() const; + + /// Retrieve the location of the cast operator keyword, e.g., + /// \c static_cast. + SourceLocation getOperatorLoc() const { return Loc; } + + /// Retrieve the location of the closing parenthesis. + SourceLocation getRParenLoc() const { return RParenLoc; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + SourceRange getAngleBrackets() const LLVM_READONLY { return AngleBrackets; } + + static bool classof(const Stmt *T) { + switch (T->getStmtClass()) { + case CXXStaticCastExprClass: + case CXXDynamicCastExprClass: + case CXXReinterpretCastExprClass: + case CXXConstCastExprClass: + case CXXAddrspaceCastExprClass: + return true; + default: + return false; + } + } +}; + +/// A C++ \c static_cast expression (C++ [expr.static.cast]). +/// +/// This expression node represents a C++ static cast, e.g., +/// \c static_cast<int>(1.0). +class CXXStaticCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *, + FPOptionsOverride> { + CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, + unsigned pathSize, TypeSourceInfo *writtenTy, + FPOptionsOverride FPO, SourceLocation l, + SourceLocation RParenLoc, SourceRange AngleBrackets) + : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize, + FPO.requiresTrailingStorage(), writtenTy, l, RParenLoc, + AngleBrackets) { + if (hasStoredFPFeatures()) + *getTrailingFPFeatures() = FPO; + } + + explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize, + bool HasFPFeatures) + : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize, + HasFPFeatures) {} + + unsigned numTrailingObjects(OverloadToken<CXXBaseSpecifier *>) const { + return path_size(); + } + +public: + friend class CastExpr; + friend TrailingObjects; + + static CXXStaticCastExpr * + Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, + Expr *Op, const CXXCastPath *Path, TypeSourceInfo *Written, + FPOptionsOverride FPO, SourceLocation L, SourceLocation RParenLoc, + SourceRange AngleBrackets); + static CXXStaticCastExpr *CreateEmpty(const ASTContext &Context, + unsigned PathSize, bool hasFPFeatures); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXStaticCastExprClass; + } +}; + +/// A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]). +/// +/// This expression node represents a dynamic cast, e.g., +/// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time +/// check to determine how to perform the type conversion. +class CXXDynamicCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> { + CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, Expr *op, + unsigned pathSize, TypeSourceInfo *writtenTy, + SourceLocation l, SourceLocation RParenLoc, + SourceRange AngleBrackets) + : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize, + /*HasFPFeatures*/ false, writtenTy, l, RParenLoc, + AngleBrackets) {} + + explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) + : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize, + /*HasFPFeatures*/ false) {} + +public: + friend class CastExpr; + friend TrailingObjects; + + static CXXDynamicCastExpr *Create(const ASTContext &Context, QualType T, + ExprValueKind VK, CastKind Kind, Expr *Op, + const CXXCastPath *Path, + TypeSourceInfo *Written, SourceLocation L, + SourceLocation RParenLoc, + SourceRange AngleBrackets); + + static CXXDynamicCastExpr *CreateEmpty(const ASTContext &Context, + unsigned pathSize); + + bool isAlwaysNull() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDynamicCastExprClass; + } +}; + +/// A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]). +/// +/// This expression node represents a reinterpret cast, e.g., +/// @c reinterpret_cast<int>(VoidPtr). +/// +/// A reinterpret_cast provides a differently-typed view of a value but +/// (in Clang, as in most C++ implementations) performs no actual work at +/// run time. +class CXXReinterpretCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXReinterpretCastExpr, + CXXBaseSpecifier *> { + CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, + unsigned pathSize, TypeSourceInfo *writtenTy, + SourceLocation l, SourceLocation RParenLoc, + SourceRange AngleBrackets) + : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op, + pathSize, /*HasFPFeatures*/ false, writtenTy, l, + RParenLoc, AngleBrackets) {} + + CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) + : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize, + /*HasFPFeatures*/ false) {} + +public: + friend class CastExpr; + friend TrailingObjects; + + static CXXReinterpretCastExpr *Create(const ASTContext &Context, QualType T, + ExprValueKind VK, CastKind Kind, + Expr *Op, const CXXCastPath *Path, + TypeSourceInfo *WrittenTy, SourceLocation L, + SourceLocation RParenLoc, + SourceRange AngleBrackets); + static CXXReinterpretCastExpr *CreateEmpty(const ASTContext &Context, + unsigned pathSize); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXReinterpretCastExprClass; + } +}; + +/// A C++ \c const_cast expression (C++ [expr.const.cast]). +/// +/// This expression node represents a const cast, e.g., +/// \c const_cast<char*>(PtrToConstChar). +/// +/// A const_cast can remove type qualifiers but does not change the underlying +/// value. +class CXXConstCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> { + CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, + TypeSourceInfo *writtenTy, SourceLocation l, + SourceLocation RParenLoc, SourceRange AngleBrackets) + : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, 0, + /*HasFPFeatures*/ false, writtenTy, l, RParenLoc, + AngleBrackets) {} + + explicit CXXConstCastExpr(EmptyShell Empty) + : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0, + /*HasFPFeatures*/ false) {} + +public: + friend class CastExpr; + friend TrailingObjects; + + static CXXConstCastExpr *Create(const ASTContext &Context, QualType T, + ExprValueKind VK, Expr *Op, + TypeSourceInfo *WrittenTy, SourceLocation L, + SourceLocation RParenLoc, + SourceRange AngleBrackets); + static CXXConstCastExpr *CreateEmpty(const ASTContext &Context); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXConstCastExprClass; + } +}; + +/// A C++ addrspace_cast expression (currently only enabled for OpenCL). +/// +/// This expression node represents a cast between pointers to objects in +/// different address spaces e.g., +/// \c addrspace_cast<global int*>(PtrToGenericInt). +/// +/// A addrspace_cast can cast address space type qualifiers but does not change +/// the underlying value. +class CXXAddrspaceCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXAddrspaceCastExpr, CXXBaseSpecifier *> { + CXXAddrspaceCastExpr(QualType ty, ExprValueKind VK, CastKind Kind, Expr *op, + TypeSourceInfo *writtenTy, SourceLocation l, + SourceLocation RParenLoc, SourceRange AngleBrackets) + : CXXNamedCastExpr(CXXAddrspaceCastExprClass, ty, VK, Kind, op, 0, + /*HasFPFeatures*/ false, writtenTy, l, RParenLoc, + AngleBrackets) {} + + explicit CXXAddrspaceCastExpr(EmptyShell Empty) + : CXXNamedCastExpr(CXXAddrspaceCastExprClass, Empty, 0, + /*HasFPFeatures*/ false) {} + +public: + friend class CastExpr; + friend TrailingObjects; + + static CXXAddrspaceCastExpr * + Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind, + Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L, + SourceLocation RParenLoc, SourceRange AngleBrackets); + static CXXAddrspaceCastExpr *CreateEmpty(const ASTContext &Context); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXAddrspaceCastExprClass; + } +}; + +/// A call to a literal operator (C++11 [over.literal]) +/// written as a user-defined literal (C++11 [lit.ext]). +/// +/// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this +/// is semantically equivalent to a normal call, this AST node provides better +/// information about the syntactic representation of the literal. +/// +/// Since literal operators are never found by ADL and can only be declared at +/// namespace scope, a user-defined literal is never dependent. +class UserDefinedLiteral final : public CallExpr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + + /// The location of a ud-suffix within the literal. + SourceLocation UDSuffixLoc; + + // UserDefinedLiteral has some trailing objects belonging + // to CallExpr. See CallExpr for the details. + + UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation LitEndLoc, + SourceLocation SuffixLoc, FPOptionsOverride FPFeatures); + + UserDefinedLiteral(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); + +public: + static UserDefinedLiteral *Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation LitEndLoc, + SourceLocation SuffixLoc, + FPOptionsOverride FPFeatures); + + static UserDefinedLiteral *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, bool HasFPOptions, + EmptyShell Empty); + + /// The kind of literal operator which is invoked. + enum LiteralOperatorKind { + /// Raw form: operator "" X (const char *) + LOK_Raw, + + /// Raw form: operator "" X<cs...> () + LOK_Template, + + /// operator "" X (unsigned long long) + LOK_Integer, + + /// operator "" X (long double) + LOK_Floating, + + /// operator "" X (const CharT *, size_t) + LOK_String, + + /// operator "" X (CharT) + LOK_Character + }; + + /// Returns the kind of literal operator invocation + /// which this expression represents. + LiteralOperatorKind getLiteralOperatorKind() const; + + /// If this is not a raw user-defined literal, get the + /// underlying cooked literal (representing the literal with the suffix + /// removed). + Expr *getCookedLiteral(); + const Expr *getCookedLiteral() const { + return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral(); + } + + SourceLocation getBeginLoc() const { + if (getLiteralOperatorKind() == LOK_Template) + return getRParenLoc(); + return getArg(0)->getBeginLoc(); + } + + SourceLocation getEndLoc() const { return getRParenLoc(); } + + /// Returns the location of a ud-suffix in the expression. + /// + /// For a string literal, there may be multiple identical suffixes. This + /// returns the first. + SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; } + + /// Returns the ud-suffix specified for this literal. + const IdentifierInfo *getUDSuffix() const; + + static bool classof(const Stmt *S) { + return S->getStmtClass() == UserDefinedLiteralClass; + } +}; + +/// A boolean literal, per ([C++ lex.bool] Boolean literals). +class CXXBoolLiteralExpr : public Expr { +public: + CXXBoolLiteralExpr(bool Val, QualType Ty, SourceLocation Loc) + : Expr(CXXBoolLiteralExprClass, Ty, VK_PRValue, OK_Ordinary) { + CXXBoolLiteralExprBits.Value = Val; + CXXBoolLiteralExprBits.Loc = Loc; + setDependence(ExprDependence::None); + } + + explicit CXXBoolLiteralExpr(EmptyShell Empty) + : Expr(CXXBoolLiteralExprClass, Empty) {} + + static CXXBoolLiteralExpr *Create(const ASTContext &C, bool Val, QualType Ty, + SourceLocation Loc) { + return new (C) CXXBoolLiteralExpr(Val, Ty, Loc); + } + + bool getValue() const { return CXXBoolLiteralExprBits.Value; } + void setValue(bool V) { CXXBoolLiteralExprBits.Value = V; } + + SourceLocation getBeginLoc() const { return getLocation(); } + SourceLocation getEndLoc() const { return getLocation(); } + + SourceLocation getLocation() const { return CXXBoolLiteralExprBits.Loc; } + void setLocation(SourceLocation L) { CXXBoolLiteralExprBits.Loc = L; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXBoolLiteralExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// The null pointer literal (C++11 [lex.nullptr]) +/// +/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr. +/// This also implements the null pointer literal in C2x (C2x 6.4.1) which is +/// intended to have the same semantics as the feature in C++. +class CXXNullPtrLiteralExpr : public Expr { +public: + CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc) + : Expr(CXXNullPtrLiteralExprClass, Ty, VK_PRValue, OK_Ordinary) { + CXXNullPtrLiteralExprBits.Loc = Loc; + setDependence(ExprDependence::None); + } + + explicit CXXNullPtrLiteralExpr(EmptyShell Empty) + : Expr(CXXNullPtrLiteralExprClass, Empty) {} + + SourceLocation getBeginLoc() const { return getLocation(); } + SourceLocation getEndLoc() const { return getLocation(); } + + SourceLocation getLocation() const { return CXXNullPtrLiteralExprBits.Loc; } + void setLocation(SourceLocation L) { CXXNullPtrLiteralExprBits.Loc = L; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXNullPtrLiteralExprClass; + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// Implicit construction of a std::initializer_list<T> object from an +/// array temporary within list-initialization (C++11 [dcl.init.list]p5). +class CXXStdInitializerListExpr : public Expr { + Stmt *SubExpr = nullptr; + + CXXStdInitializerListExpr(EmptyShell Empty) + : Expr(CXXStdInitializerListExprClass, Empty) {} + +public: + friend class ASTReader; + friend class ASTStmtReader; + + CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr) + : Expr(CXXStdInitializerListExprClass, Ty, VK_PRValue, OK_Ordinary), + SubExpr(SubExpr) { + setDependence(computeDependence(this)); + } + + Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); } + const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return SubExpr->getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + return SubExpr->getEndLoc(); + } + + /// Retrieve the source range of the expression. + SourceRange getSourceRange() const LLVM_READONLY { + return SubExpr->getSourceRange(); + } + + static bool classof(const Stmt *S) { + return S->getStmtClass() == CXXStdInitializerListExprClass; + } + + child_range children() { return child_range(&SubExpr, &SubExpr + 1); } + + const_child_range children() const { + return const_child_range(&SubExpr, &SubExpr + 1); + } +}; + +/// A C++ \c typeid expression (C++ [expr.typeid]), which gets +/// the \c type_info that corresponds to the supplied type, or the (possibly +/// dynamic) type of the supplied expression. +/// +/// This represents code like \c typeid(int) or \c typeid(*objPtr) +class CXXTypeidExpr : public Expr { + friend class ASTStmtReader; + +private: + llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; + SourceRange Range; + +public: + CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) + : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), + Range(R) { + setDependence(computeDependence(this)); + } + + CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) + : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), + Range(R) { + setDependence(computeDependence(this)); + } + + CXXTypeidExpr(EmptyShell Empty, bool isExpr) + : Expr(CXXTypeidExprClass, Empty) { + if (isExpr) + Operand = (Expr*)nullptr; + else + Operand = (TypeSourceInfo*)nullptr; + } + + /// Determine whether this typeid has a type operand which is potentially + /// evaluated, per C++11 [expr.typeid]p3. + bool isPotentiallyEvaluated() const; + + /// Best-effort check if the expression operand refers to a most derived + /// object. This is not a strong guarantee. + bool isMostDerived(ASTContext &Context) const; + + bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } + + /// Retrieves the type operand of this typeid() expression after + /// various required adjustments (removing reference types, cv-qualifiers). + QualType getTypeOperand(ASTContext &Context) const; + + /// Retrieve source information for the type operand. + TypeSourceInfo *getTypeOperandSourceInfo() const { + assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); + return Operand.get<TypeSourceInfo *>(); + } + Expr *getExprOperand() const { + assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); + return static_cast<Expr*>(Operand.get<Stmt *>()); + } + + SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } + void setSourceRange(SourceRange R) { Range = R; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXTypeidExprClass; + } + + // Iterators + child_range children() { + if (isTypeOperand()) + return child_range(child_iterator(), child_iterator()); + auto **begin = reinterpret_cast<Stmt **>(&Operand); + return child_range(begin, begin + 1); + } + + const_child_range children() const { + if (isTypeOperand()) + return const_child_range(const_child_iterator(), const_child_iterator()); + + auto **begin = + reinterpret_cast<Stmt **>(&const_cast<CXXTypeidExpr *>(this)->Operand); + return const_child_range(begin, begin + 1); + } +}; + +/// A member reference to an MSPropertyDecl. +/// +/// This expression always has pseudo-object type, and therefore it is +/// typically not encountered in a fully-typechecked expression except +/// within the syntactic form of a PseudoObjectExpr. +class MSPropertyRefExpr : public Expr { + Expr *BaseExpr; + MSPropertyDecl *TheDecl; + SourceLocation MemberLoc; + bool IsArrow; + NestedNameSpecifierLoc QualifierLoc; + +public: + friend class ASTStmtReader; + + MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow, + QualType ty, ExprValueKind VK, + NestedNameSpecifierLoc qualifierLoc, SourceLocation nameLoc) + : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary), BaseExpr(baseExpr), + TheDecl(decl), MemberLoc(nameLoc), IsArrow(isArrow), + QualifierLoc(qualifierLoc) { + setDependence(computeDependence(this)); + } + + MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {} + + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(getBeginLoc(), getEndLoc()); + } + + bool isImplicitAccess() const { + return getBaseExpr() && getBaseExpr()->isImplicitCXXThis(); + } + + SourceLocation getBeginLoc() const { + if (!isImplicitAccess()) + return BaseExpr->getBeginLoc(); + else if (QualifierLoc) + return QualifierLoc.getBeginLoc(); + else + return MemberLoc; + } + + SourceLocation getEndLoc() const { return getMemberLoc(); } + + child_range children() { + return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1); + } + + const_child_range children() const { + auto Children = const_cast<MSPropertyRefExpr *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == MSPropertyRefExprClass; + } + + Expr *getBaseExpr() const { return BaseExpr; } + MSPropertyDecl *getPropertyDecl() const { return TheDecl; } + bool isArrow() const { return IsArrow; } + SourceLocation getMemberLoc() const { return MemberLoc; } + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } +}; + +/// MS property subscript expression. +/// MSVC supports 'property' attribute and allows to apply it to the +/// declaration of an empty array in a class or structure definition. +/// For example: +/// \code +/// __declspec(property(get=GetX, put=PutX)) int x[]; +/// \endcode +/// The above statement indicates that x[] can be used with one or more array +/// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and +/// p->x[a][b] = i will be turned into p->PutX(a, b, i). +/// This is a syntactic pseudo-object expression. +class MSPropertySubscriptExpr : public Expr { + friend class ASTStmtReader; + + enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 }; + + Stmt *SubExprs[NUM_SUBEXPRS]; + SourceLocation RBracketLoc; + + void setBase(Expr *Base) { SubExprs[BASE_EXPR] = Base; } + void setIdx(Expr *Idx) { SubExprs[IDX_EXPR] = Idx; } + +public: + MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK, + ExprObjectKind OK, SourceLocation RBracketLoc) + : Expr(MSPropertySubscriptExprClass, Ty, VK, OK), + RBracketLoc(RBracketLoc) { + SubExprs[BASE_EXPR] = Base; + SubExprs[IDX_EXPR] = Idx; + setDependence(computeDependence(this)); + } + + /// Create an empty array subscript expression. + explicit MSPropertySubscriptExpr(EmptyShell Shell) + : Expr(MSPropertySubscriptExprClass, Shell) {} + + Expr *getBase() { return cast<Expr>(SubExprs[BASE_EXPR]); } + const Expr *getBase() const { return cast<Expr>(SubExprs[BASE_EXPR]); } + + Expr *getIdx() { return cast<Expr>(SubExprs[IDX_EXPR]); } + const Expr *getIdx() const { return cast<Expr>(SubExprs[IDX_EXPR]); } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return getBase()->getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; } + + SourceLocation getRBracketLoc() const { return RBracketLoc; } + void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } + + SourceLocation getExprLoc() const LLVM_READONLY { + return getBase()->getExprLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == MSPropertySubscriptExprClass; + } + + // Iterators + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS); + } + + const_child_range children() const { + return const_child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS); + } +}; + +/// A Microsoft C++ @c __uuidof expression, which gets +/// the _GUID that corresponds to the supplied type or expression. +/// +/// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr) +class CXXUuidofExpr : public Expr { + friend class ASTStmtReader; + +private: + llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; + MSGuidDecl *Guid; + SourceRange Range; + +public: + CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, MSGuidDecl *Guid, + SourceRange R) + : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), + Guid(Guid), Range(R) { + setDependence(computeDependence(this)); + } + + CXXUuidofExpr(QualType Ty, Expr *Operand, MSGuidDecl *Guid, SourceRange R) + : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), + Guid(Guid), Range(R) { + setDependence(computeDependence(this)); + } + + CXXUuidofExpr(EmptyShell Empty, bool isExpr) + : Expr(CXXUuidofExprClass, Empty) { + if (isExpr) + Operand = (Expr*)nullptr; + else + Operand = (TypeSourceInfo*)nullptr; + } + + bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } + + /// Retrieves the type operand of this __uuidof() expression after + /// various required adjustments (removing reference types, cv-qualifiers). + QualType getTypeOperand(ASTContext &Context) const; + + /// Retrieve source information for the type operand. + TypeSourceInfo *getTypeOperandSourceInfo() const { + assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); + return Operand.get<TypeSourceInfo *>(); + } + Expr *getExprOperand() const { + assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); + return static_cast<Expr*>(Operand.get<Stmt *>()); + } + + MSGuidDecl *getGuidDecl() const { return Guid; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } + void setSourceRange(SourceRange R) { Range = R; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXUuidofExprClass; + } + + // Iterators + child_range children() { + if (isTypeOperand()) + return child_range(child_iterator(), child_iterator()); + auto **begin = reinterpret_cast<Stmt **>(&Operand); + return child_range(begin, begin + 1); + } + + const_child_range children() const { + if (isTypeOperand()) + return const_child_range(const_child_iterator(), const_child_iterator()); + auto **begin = + reinterpret_cast<Stmt **>(&const_cast<CXXUuidofExpr *>(this)->Operand); + return const_child_range(begin, begin + 1); + } +}; + +/// Represents the \c this expression in C++. +/// +/// This is a pointer to the object on which the current member function is +/// executing (C++ [expr.prim]p3). Example: +/// +/// \code +/// class Foo { +/// public: +/// void bar(); +/// void test() { this->bar(); } +/// }; +/// \endcode +class CXXThisExpr : public Expr { +public: + CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit) + : Expr(CXXThisExprClass, Ty, VK_PRValue, OK_Ordinary) { + CXXThisExprBits.IsImplicit = IsImplicit; + CXXThisExprBits.Loc = L; + setDependence(computeDependence(this)); + } + + CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} + + SourceLocation getLocation() const { return CXXThisExprBits.Loc; } + void setLocation(SourceLocation L) { CXXThisExprBits.Loc = L; } + + SourceLocation getBeginLoc() const { return getLocation(); } + SourceLocation getEndLoc() const { return getLocation(); } + + bool isImplicit() const { return CXXThisExprBits.IsImplicit; } + void setImplicit(bool I) { CXXThisExprBits.IsImplicit = I; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXThisExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// A C++ throw-expression (C++ [except.throw]). +/// +/// This handles 'throw' (for re-throwing the current exception) and +/// 'throw' assignment-expression. When assignment-expression isn't +/// present, Op will be null. +class CXXThrowExpr : public Expr { + friend class ASTStmtReader; + + /// The optional expression in the throw statement. + Stmt *Operand; + +public: + // \p Ty is the void type which is used as the result type of the + // expression. The \p Loc is the location of the throw keyword. + // \p Operand is the expression in the throw statement, and can be + // null if not present. + CXXThrowExpr(Expr *Operand, QualType Ty, SourceLocation Loc, + bool IsThrownVariableInScope) + : Expr(CXXThrowExprClass, Ty, VK_PRValue, OK_Ordinary), Operand(Operand) { + CXXThrowExprBits.ThrowLoc = Loc; + CXXThrowExprBits.IsThrownVariableInScope = IsThrownVariableInScope; + setDependence(computeDependence(this)); + } + CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} + + const Expr *getSubExpr() const { return cast_or_null<Expr>(Operand); } + Expr *getSubExpr() { return cast_or_null<Expr>(Operand); } + + SourceLocation getThrowLoc() const { return CXXThrowExprBits.ThrowLoc; } + + /// Determines whether the variable thrown by this expression (if any!) + /// is within the innermost try block. + /// + /// This information is required to determine whether the NRVO can apply to + /// this variable. + bool isThrownVariableInScope() const { + return CXXThrowExprBits.IsThrownVariableInScope; + } + + SourceLocation getBeginLoc() const { return getThrowLoc(); } + SourceLocation getEndLoc() const LLVM_READONLY { + if (!getSubExpr()) + return getThrowLoc(); + return getSubExpr()->getEndLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXThrowExprClass; + } + + // Iterators + child_range children() { + return child_range(&Operand, Operand ? &Operand + 1 : &Operand); + } + + const_child_range children() const { + return const_child_range(&Operand, Operand ? &Operand + 1 : &Operand); + } +}; + +/// A default argument (C++ [dcl.fct.default]). +/// +/// This wraps up a function call argument that was created from the +/// corresponding parameter's default argument, when the call did not +/// explicitly supply arguments for all of the parameters. +class CXXDefaultArgExpr final + : public Expr, + private llvm::TrailingObjects<CXXDefaultArgExpr, Expr *> { + friend class ASTStmtReader; + friend class ASTReader; + friend TrailingObjects; + + /// The parameter whose default is being used. + ParmVarDecl *Param; + + /// The context where the default argument expression was used. + DeclContext *UsedContext; + + CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param, + Expr *RewrittenExpr, DeclContext *UsedContext) + : Expr(SC, + Param->hasUnparsedDefaultArg() + ? Param->getType().getNonReferenceType() + : Param->getDefaultArg()->getType(), + Param->getDefaultArg()->getValueKind(), + Param->getDefaultArg()->getObjectKind()), + Param(Param), UsedContext(UsedContext) { + CXXDefaultArgExprBits.Loc = Loc; + CXXDefaultArgExprBits.HasRewrittenInit = RewrittenExpr != nullptr; + if (RewrittenExpr) + *getTrailingObjects<Expr *>() = RewrittenExpr; + setDependence(computeDependence(this)); + } + + CXXDefaultArgExpr(EmptyShell Empty, bool HasRewrittenInit) + : Expr(CXXDefaultArgExprClass, Empty) { + CXXDefaultArgExprBits.HasRewrittenInit = HasRewrittenInit; + } + +public: + static CXXDefaultArgExpr *CreateEmpty(const ASTContext &C, + bool HasRewrittenInit); + + // \p Param is the parameter whose default argument is used by this + // expression. + static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc, + ParmVarDecl *Param, Expr *RewrittenExpr, + DeclContext *UsedContext); + // Retrieve the parameter that the argument was created from. + const ParmVarDecl *getParam() const { return Param; } + ParmVarDecl *getParam() { return Param; } + + bool hasRewrittenInit() const { + return CXXDefaultArgExprBits.HasRewrittenInit; + } + + // Retrieve the argument to the function call. + Expr *getExpr(); + const Expr *getExpr() const { + return const_cast<CXXDefaultArgExpr *>(this)->getExpr(); + } + + Expr *getRewrittenExpr() { + return hasRewrittenInit() ? *getTrailingObjects<Expr *>() : nullptr; + } + + const Expr *getRewrittenExpr() const { + return const_cast<CXXDefaultArgExpr *>(this)->getRewrittenExpr(); + } + + // Retrieve the rewritten init expression (for an init expression containing + // immediate calls) with the top level FullExpr and ConstantExpr stripped off. + Expr *getAdjustedRewrittenExpr(); + const Expr *getAdjustedRewrittenExpr() const { + return const_cast<CXXDefaultArgExpr *>(this)->getAdjustedRewrittenExpr(); + } + + const DeclContext *getUsedContext() const { return UsedContext; } + DeclContext *getUsedContext() { return UsedContext; } + + /// Retrieve the location where this default argument was actually used. + SourceLocation getUsedLocation() const { return CXXDefaultArgExprBits.Loc; } + + /// Default argument expressions have no representation in the + /// source, so they have an empty source range. + SourceLocation getBeginLoc() const { return SourceLocation(); } + SourceLocation getEndLoc() const { return SourceLocation(); } + + SourceLocation getExprLoc() const { return getUsedLocation(); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDefaultArgExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// A use of a default initializer in a constructor or in aggregate +/// initialization. +/// +/// This wraps a use of a C++ default initializer (technically, +/// a brace-or-equal-initializer for a non-static data member) when it +/// is implicitly used in a mem-initializer-list in a constructor +/// (C++11 [class.base.init]p8) or in aggregate initialization +/// (C++1y [dcl.init.aggr]p7). +class CXXDefaultInitExpr final + : public Expr, + private llvm::TrailingObjects<CXXDefaultInitExpr, Expr *> { + + friend class ASTStmtReader; + friend class ASTReader; + friend TrailingObjects; + /// The field whose default is being used. + FieldDecl *Field; + + /// The context where the default initializer expression was used. + DeclContext *UsedContext; + + CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc, + FieldDecl *Field, QualType Ty, DeclContext *UsedContext, + Expr *RewrittenInitExpr); + + CXXDefaultInitExpr(EmptyShell Empty, bool HasRewrittenInit) + : Expr(CXXDefaultInitExprClass, Empty) { + CXXDefaultInitExprBits.HasRewrittenInit = HasRewrittenInit; + } + +public: + static CXXDefaultInitExpr *CreateEmpty(const ASTContext &C, + bool HasRewrittenInit); + /// \p Field is the non-static data member whose default initializer is used + /// by this expression. + static CXXDefaultInitExpr *Create(const ASTContext &Ctx, SourceLocation Loc, + FieldDecl *Field, DeclContext *UsedContext, + Expr *RewrittenInitExpr); + + bool hasRewrittenInit() const { + return CXXDefaultInitExprBits.HasRewrittenInit; + } + + /// Get the field whose initializer will be used. + FieldDecl *getField() { return Field; } + const FieldDecl *getField() const { return Field; } + + /// Get the initialization expression that will be used. + Expr *getExpr(); + const Expr *getExpr() const { + return const_cast<CXXDefaultInitExpr *>(this)->getExpr(); + } + + /// Retrieve the initializing expression with evaluated immediate calls, if + /// any. + const Expr *getRewrittenExpr() const { + assert(hasRewrittenInit() && "expected a rewritten init expression"); + return *getTrailingObjects<Expr *>(); + } + + /// Retrieve the initializing expression with evaluated immediate calls, if + /// any. + Expr *getRewrittenExpr() { + assert(hasRewrittenInit() && "expected a rewritten init expression"); + return *getTrailingObjects<Expr *>(); + } + + const DeclContext *getUsedContext() const { return UsedContext; } + DeclContext *getUsedContext() { return UsedContext; } + + /// Retrieve the location where this default initializer expression was + /// actually used. + SourceLocation getUsedLocation() const { return getBeginLoc(); } + + SourceLocation getBeginLoc() const { return CXXDefaultInitExprBits.Loc; } + SourceLocation getEndLoc() const { return CXXDefaultInitExprBits.Loc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDefaultInitExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// Represents a C++ temporary. +class CXXTemporary { + /// The destructor that needs to be called. + const CXXDestructorDecl *Destructor; + + explicit CXXTemporary(const CXXDestructorDecl *destructor) + : Destructor(destructor) {} + +public: + static CXXTemporary *Create(const ASTContext &C, + const CXXDestructorDecl *Destructor); + + const CXXDestructorDecl *getDestructor() const { return Destructor; } + + void setDestructor(const CXXDestructorDecl *Dtor) { + Destructor = Dtor; + } +}; + +/// Represents binding an expression to a temporary. +/// +/// This ensures the destructor is called for the temporary. It should only be +/// needed for non-POD, non-trivially destructable class types. For example: +/// +/// \code +/// struct S { +/// S() { } // User defined constructor makes S non-POD. +/// ~S() { } // User defined destructor makes it non-trivial. +/// }; +/// void test() { +/// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr. +/// } +/// \endcode +class CXXBindTemporaryExpr : public Expr { + CXXTemporary *Temp = nullptr; + Stmt *SubExpr = nullptr; + + CXXBindTemporaryExpr(CXXTemporary *temp, Expr *SubExpr) + : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), VK_PRValue, + OK_Ordinary), + Temp(temp), SubExpr(SubExpr) { + setDependence(computeDependence(this)); + } + +public: + CXXBindTemporaryExpr(EmptyShell Empty) + : Expr(CXXBindTemporaryExprClass, Empty) {} + + static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp, + Expr* SubExpr); + + CXXTemporary *getTemporary() { return Temp; } + const CXXTemporary *getTemporary() const { return Temp; } + void setTemporary(CXXTemporary *T) { Temp = T; } + + const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } + Expr *getSubExpr() { return cast<Expr>(SubExpr); } + void setSubExpr(Expr *E) { SubExpr = E; } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return SubExpr->getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + return SubExpr->getEndLoc(); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXBindTemporaryExprClass; + } + + // Iterators + child_range children() { return child_range(&SubExpr, &SubExpr + 1); } + + const_child_range children() const { + return const_child_range(&SubExpr, &SubExpr + 1); + } +}; + +/// Represents a call to a C++ constructor. +class CXXConstructExpr : public Expr { + friend class ASTStmtReader; + +public: + enum ConstructionKind { + CK_Complete, + CK_NonVirtualBase, + CK_VirtualBase, + CK_Delegating + }; + +private: + /// A pointer to the constructor which will be ultimately called. + CXXConstructorDecl *Constructor; + + SourceRange ParenOrBraceRange; + + /// The number of arguments. + unsigned NumArgs; + + // We would like to stash the arguments of the constructor call after + // CXXConstructExpr. However CXXConstructExpr is used as a base class of + // CXXTemporaryObjectExpr which makes the use of llvm::TrailingObjects + // impossible. + // + // Instead we manually stash the trailing object after the full object + // containing CXXConstructExpr (that is either CXXConstructExpr or + // CXXTemporaryObjectExpr). + // + // The trailing objects are: + // + // * An array of getNumArgs() "Stmt *" for the arguments of the + // constructor call. + + /// Return a pointer to the start of the trailing arguments. + /// Defined just after CXXTemporaryObjectExpr. + inline Stmt **getTrailingArgs(); + const Stmt *const *getTrailingArgs() const { + return const_cast<CXXConstructExpr *>(this)->getTrailingArgs(); + } + +protected: + /// Build a C++ construction expression. + CXXConstructExpr(StmtClass SC, QualType Ty, SourceLocation Loc, + CXXConstructorDecl *Ctor, bool Elidable, + ArrayRef<Expr *> Args, bool HadMultipleCandidates, + bool ListInitialization, bool StdInitListInitialization, + bool ZeroInitialization, ConstructionKind ConstructKind, + SourceRange ParenOrBraceRange); + + /// Build an empty C++ construction expression. + CXXConstructExpr(StmtClass SC, EmptyShell Empty, unsigned NumArgs); + + /// Return the size in bytes of the trailing objects. Used by + /// CXXTemporaryObjectExpr to allocate the right amount of storage. + static unsigned sizeOfTrailingObjects(unsigned NumArgs) { + return NumArgs * sizeof(Stmt *); + } + +public: + /// Create a C++ construction expression. + static CXXConstructExpr * + Create(const ASTContext &Ctx, QualType Ty, SourceLocation Loc, + CXXConstructorDecl *Ctor, bool Elidable, ArrayRef<Expr *> Args, + bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, + ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); + + /// Create an empty C++ construction expression. + static CXXConstructExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs); + + /// Get the constructor that this expression will (ultimately) call. + CXXConstructorDecl *getConstructor() const { return Constructor; } + + SourceLocation getLocation() const { return CXXConstructExprBits.Loc; } + void setLocation(SourceLocation Loc) { CXXConstructExprBits.Loc = Loc; } + + /// Whether this construction is elidable. + bool isElidable() const { return CXXConstructExprBits.Elidable; } + void setElidable(bool E) { CXXConstructExprBits.Elidable = E; } + + /// Whether the referred constructor was resolved from + /// an overloaded set having size greater than 1. + bool hadMultipleCandidates() const { + return CXXConstructExprBits.HadMultipleCandidates; + } + void setHadMultipleCandidates(bool V) { + CXXConstructExprBits.HadMultipleCandidates = V; + } + + /// Whether this constructor call was written as list-initialization. + bool isListInitialization() const { + return CXXConstructExprBits.ListInitialization; + } + void setListInitialization(bool V) { + CXXConstructExprBits.ListInitialization = V; + } + + /// Whether this constructor call was written as list-initialization, + /// but was interpreted as forming a std::initializer_list<T> from the list + /// and passing that as a single constructor argument. + /// See C++11 [over.match.list]p1 bullet 1. + bool isStdInitListInitialization() const { + return CXXConstructExprBits.StdInitListInitialization; + } + void setStdInitListInitialization(bool V) { + CXXConstructExprBits.StdInitListInitialization = V; + } + + /// Whether this construction first requires + /// zero-initialization before the initializer is called. + bool requiresZeroInitialization() const { + return CXXConstructExprBits.ZeroInitialization; + } + void setRequiresZeroInitialization(bool ZeroInit) { + CXXConstructExprBits.ZeroInitialization = ZeroInit; + } + + /// Determine whether this constructor is actually constructing + /// a base class (rather than a complete object). + ConstructionKind getConstructionKind() const { + return static_cast<ConstructionKind>(CXXConstructExprBits.ConstructionKind); + } + void setConstructionKind(ConstructionKind CK) { + CXXConstructExprBits.ConstructionKind = CK; + } + + using arg_iterator = ExprIterator; + using const_arg_iterator = ConstExprIterator; + using arg_range = llvm::iterator_range<arg_iterator>; + using const_arg_range = llvm::iterator_range<const_arg_iterator>; + + arg_range arguments() { return arg_range(arg_begin(), arg_end()); } + const_arg_range arguments() const { + return const_arg_range(arg_begin(), arg_end()); + } + + arg_iterator arg_begin() { return getTrailingArgs(); } + arg_iterator arg_end() { return arg_begin() + getNumArgs(); } + const_arg_iterator arg_begin() const { return getTrailingArgs(); } + const_arg_iterator arg_end() const { return arg_begin() + getNumArgs(); } + + Expr **getArgs() { return reinterpret_cast<Expr **>(getTrailingArgs()); } + const Expr *const *getArgs() const { + return reinterpret_cast<const Expr *const *>(getTrailingArgs()); + } + + /// Return the number of arguments to the constructor call. + unsigned getNumArgs() const { return NumArgs; } + + /// Return the specified argument. + Expr *getArg(unsigned Arg) { + assert(Arg < getNumArgs() && "Arg access out of range!"); + return getArgs()[Arg]; + } + const Expr *getArg(unsigned Arg) const { + assert(Arg < getNumArgs() && "Arg access out of range!"); + return getArgs()[Arg]; + } + + /// Set the specified argument. + void setArg(unsigned Arg, Expr *ArgExpr) { + assert(Arg < getNumArgs() && "Arg access out of range!"); + getArgs()[Arg] = ArgExpr; + } + + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; + SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; } + void setParenOrBraceRange(SourceRange Range) { ParenOrBraceRange = Range; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXConstructExprClass || + T->getStmtClass() == CXXTemporaryObjectExprClass; + } + + // Iterators + child_range children() { + return child_range(getTrailingArgs(), getTrailingArgs() + getNumArgs()); + } + + const_child_range children() const { + auto Children = const_cast<CXXConstructExpr *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } +}; + +/// Represents a call to an inherited base class constructor from an +/// inheriting constructor. This call implicitly forwards the arguments from +/// the enclosing context (an inheriting constructor) to the specified inherited +/// base class constructor. +class CXXInheritedCtorInitExpr : public Expr { +private: + CXXConstructorDecl *Constructor = nullptr; + + /// The location of the using declaration. + SourceLocation Loc; + + /// Whether this is the construction of a virtual base. + unsigned ConstructsVirtualBase : 1; + + /// Whether the constructor is inherited from a virtual base class of the + /// class that we construct. + unsigned InheritedFromVirtualBase : 1; + +public: + friend class ASTStmtReader; + + /// Construct a C++ inheriting construction expression. + CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T, + CXXConstructorDecl *Ctor, bool ConstructsVirtualBase, + bool InheritedFromVirtualBase) + : Expr(CXXInheritedCtorInitExprClass, T, VK_PRValue, OK_Ordinary), + Constructor(Ctor), Loc(Loc), + ConstructsVirtualBase(ConstructsVirtualBase), + InheritedFromVirtualBase(InheritedFromVirtualBase) { + assert(!T->isDependentType()); + setDependence(ExprDependence::None); + } + + /// Construct an empty C++ inheriting construction expression. + explicit CXXInheritedCtorInitExpr(EmptyShell Empty) + : Expr(CXXInheritedCtorInitExprClass, Empty), + ConstructsVirtualBase(false), InheritedFromVirtualBase(false) {} + + /// Get the constructor that this expression will call. + CXXConstructorDecl *getConstructor() const { return Constructor; } + + /// Determine whether this constructor is actually constructing + /// a base class (rather than a complete object). + bool constructsVBase() const { return ConstructsVirtualBase; } + CXXConstructExpr::ConstructionKind getConstructionKind() const { + return ConstructsVirtualBase ? CXXConstructExpr::CK_VirtualBase + : CXXConstructExpr::CK_NonVirtualBase; + } + + /// Determine whether the inherited constructor is inherited from a + /// virtual base of the object we construct. If so, we are not responsible + /// for calling the inherited constructor (the complete object constructor + /// does that), and so we don't need to pass any arguments. + bool inheritedFromVBase() const { return InheritedFromVirtualBase; } + + SourceLocation getLocation() const LLVM_READONLY { return Loc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXInheritedCtorInitExprClass; + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// Represents an explicit C++ type conversion that uses "functional" +/// notation (C++ [expr.type.conv]). +/// +/// Example: +/// \code +/// x = int(0.5); +/// \endcode +class CXXFunctionalCastExpr final + : public ExplicitCastExpr, + private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *, + FPOptionsOverride> { + SourceLocation LParenLoc; + SourceLocation RParenLoc; + + CXXFunctionalCastExpr(QualType ty, ExprValueKind VK, + TypeSourceInfo *writtenTy, CastKind kind, + Expr *castExpr, unsigned pathSize, + FPOptionsOverride FPO, SourceLocation lParenLoc, + SourceLocation rParenLoc) + : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, castExpr, + pathSize, FPO.requiresTrailingStorage(), writtenTy), + LParenLoc(lParenLoc), RParenLoc(rParenLoc) { + if (hasStoredFPFeatures()) + *getTrailingFPFeatures() = FPO; + } + + explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize, + bool HasFPFeatures) + : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize, + HasFPFeatures) {} + + unsigned numTrailingObjects(OverloadToken<CXXBaseSpecifier *>) const { + return path_size(); + } + +public: + friend class CastExpr; + friend TrailingObjects; + + static CXXFunctionalCastExpr * + Create(const ASTContext &Context, QualType T, ExprValueKind VK, + TypeSourceInfo *Written, CastKind Kind, Expr *Op, + const CXXCastPath *Path, FPOptionsOverride FPO, SourceLocation LPLoc, + SourceLocation RPLoc); + static CXXFunctionalCastExpr * + CreateEmpty(const ASTContext &Context, unsigned PathSize, bool HasFPFeatures); + + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + /// Determine whether this expression models list-initialization. + bool isListInitialization() const { return LParenLoc.isInvalid(); } + + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXFunctionalCastExprClass; + } +}; + +/// Represents a C++ functional cast expression that builds a +/// temporary object. +/// +/// This expression type represents a C++ "functional" cast +/// (C++[expr.type.conv]) with N != 1 arguments that invokes a +/// constructor to build a temporary object. With N == 1 arguments the +/// functional cast expression will be represented by CXXFunctionalCastExpr. +/// Example: +/// \code +/// struct X { X(int, float); } +/// +/// X create_X() { +/// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr +/// }; +/// \endcode +class CXXTemporaryObjectExpr final : public CXXConstructExpr { + friend class ASTStmtReader; + + // CXXTemporaryObjectExpr has some trailing objects belonging + // to CXXConstructExpr. See the comment inside CXXConstructExpr + // for more details. + + TypeSourceInfo *TSI; + + CXXTemporaryObjectExpr(CXXConstructorDecl *Cons, QualType Ty, + TypeSourceInfo *TSI, ArrayRef<Expr *> Args, + SourceRange ParenOrBraceRange, + bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, + bool ZeroInitialization); + + CXXTemporaryObjectExpr(EmptyShell Empty, unsigned NumArgs); + +public: + static CXXTemporaryObjectExpr * + Create(const ASTContext &Ctx, CXXConstructorDecl *Cons, QualType Ty, + TypeSourceInfo *TSI, ArrayRef<Expr *> Args, + SourceRange ParenOrBraceRange, bool HadMultipleCandidates, + bool ListInitialization, bool StdInitListInitialization, + bool ZeroInitialization); + + static CXXTemporaryObjectExpr *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs); + + TypeSourceInfo *getTypeSourceInfo() const { return TSI; } + + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXTemporaryObjectExprClass; + } +}; + +Stmt **CXXConstructExpr::getTrailingArgs() { + if (auto *E = dyn_cast<CXXTemporaryObjectExpr>(this)) + return reinterpret_cast<Stmt **>(E + 1); + assert((getStmtClass() == CXXConstructExprClass) && + "Unexpected class deriving from CXXConstructExpr!"); + return reinterpret_cast<Stmt **>(this + 1); +} + +/// A C++ lambda expression, which produces a function object +/// (of unspecified type) that can be invoked later. +/// +/// Example: +/// \code +/// void low_pass_filter(std::vector<double> &values, double cutoff) { +/// values.erase(std::remove_if(values.begin(), values.end(), +/// [=](double value) { return value > cutoff; }); +/// } +/// \endcode +/// +/// C++11 lambda expressions can capture local variables, either by copying +/// the values of those local variables at the time the function +/// object is constructed (not when it is called!) or by holding a +/// reference to the local variable. These captures can occur either +/// implicitly or can be written explicitly between the square +/// brackets ([...]) that start the lambda expression. +/// +/// C++1y introduces a new form of "capture" called an init-capture that +/// includes an initializing expression (rather than capturing a variable), +/// and which can never occur implicitly. +class LambdaExpr final : public Expr, + private llvm::TrailingObjects<LambdaExpr, Stmt *> { + // LambdaExpr has some data stored in LambdaExprBits. + + /// The source range that covers the lambda introducer ([...]). + SourceRange IntroducerRange; + + /// The source location of this lambda's capture-default ('=' or '&'). + SourceLocation CaptureDefaultLoc; + + /// The location of the closing brace ('}') that completes + /// the lambda. + /// + /// The location of the brace is also available by looking up the + /// function call operator in the lambda class. However, it is + /// stored here to improve the performance of getSourceRange(), and + /// to avoid having to deserialize the function call operator from a + /// module file just to determine the source range. + SourceLocation ClosingBrace; + + /// Construct a lambda expression. + LambdaExpr(QualType T, SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + SourceLocation CaptureDefaultLoc, bool ExplicitParams, + bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, + SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack); + + /// Construct an empty lambda expression. + LambdaExpr(EmptyShell Empty, unsigned NumCaptures); + + Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); } + Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); } + + void initBodyIfNeeded() const; + +public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + + /// Construct a new lambda expression. + static LambdaExpr * + Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, + bool ExplicitParams, bool ExplicitResultType, + ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace, + bool ContainsUnexpandedParameterPack); + + /// Construct a new lambda expression that will be deserialized from + /// an external source. + static LambdaExpr *CreateDeserialized(const ASTContext &C, + unsigned NumCaptures); + + /// Determine the default capture kind for this lambda. + LambdaCaptureDefault getCaptureDefault() const { + return static_cast<LambdaCaptureDefault>(LambdaExprBits.CaptureDefault); + } + + /// Retrieve the location of this lambda's capture-default, if any. + SourceLocation getCaptureDefaultLoc() const { return CaptureDefaultLoc; } + + /// Determine whether one of this lambda's captures is an init-capture. + bool isInitCapture(const LambdaCapture *Capture) const; + + /// An iterator that walks over the captures of the lambda, + /// both implicit and explicit. + using capture_iterator = const LambdaCapture *; + + /// An iterator over a range of lambda captures. + using capture_range = llvm::iterator_range<capture_iterator>; + + /// Retrieve this lambda's captures. + capture_range captures() const; + + /// Retrieve an iterator pointing to the first lambda capture. + capture_iterator capture_begin() const; + + /// Retrieve an iterator pointing past the end of the + /// sequence of lambda captures. + capture_iterator capture_end() const; + + /// Determine the number of captures in this lambda. + unsigned capture_size() const { return LambdaExprBits.NumCaptures; } + + /// Retrieve this lambda's explicit captures. + capture_range explicit_captures() const; + + /// Retrieve an iterator pointing to the first explicit + /// lambda capture. + capture_iterator explicit_capture_begin() const; + + /// Retrieve an iterator pointing past the end of the sequence of + /// explicit lambda captures. + capture_iterator explicit_capture_end() const; + + /// Retrieve this lambda's implicit captures. + capture_range implicit_captures() const; + + /// Retrieve an iterator pointing to the first implicit + /// lambda capture. + capture_iterator implicit_capture_begin() const; + + /// Retrieve an iterator pointing past the end of the sequence of + /// implicit lambda captures. + capture_iterator implicit_capture_end() const; + + /// Iterator that walks over the capture initialization + /// arguments. + using capture_init_iterator = Expr **; + + /// Const iterator that walks over the capture initialization + /// arguments. + /// FIXME: This interface is prone to being used incorrectly. + using const_capture_init_iterator = Expr *const *; + + /// Retrieve the initialization expressions for this lambda's captures. + llvm::iterator_range<capture_init_iterator> capture_inits() { + return llvm::make_range(capture_init_begin(), capture_init_end()); + } + + /// Retrieve the initialization expressions for this lambda's captures. + llvm::iterator_range<const_capture_init_iterator> capture_inits() const { + return llvm::make_range(capture_init_begin(), capture_init_end()); + } + + /// Retrieve the first initialization argument for this + /// lambda expression (which initializes the first capture field). + capture_init_iterator capture_init_begin() { + return reinterpret_cast<Expr **>(getStoredStmts()); + } + + /// Retrieve the first initialization argument for this + /// lambda expression (which initializes the first capture field). + const_capture_init_iterator capture_init_begin() const { + return reinterpret_cast<Expr *const *>(getStoredStmts()); + } + + /// Retrieve the iterator pointing one past the last + /// initialization argument for this lambda expression. + capture_init_iterator capture_init_end() { + return capture_init_begin() + capture_size(); + } + + /// Retrieve the iterator pointing one past the last + /// initialization argument for this lambda expression. + const_capture_init_iterator capture_init_end() const { + return capture_init_begin() + capture_size(); + } + + /// Retrieve the source range covering the lambda introducer, + /// which contains the explicit capture list surrounded by square + /// brackets ([...]). + SourceRange getIntroducerRange() const { return IntroducerRange; } + + /// Retrieve the class that corresponds to the lambda. + /// + /// This is the "closure type" (C++1y [expr.prim.lambda]), and stores the + /// captures in its fields and provides the various operations permitted + /// on a lambda (copying, calling). + CXXRecordDecl *getLambdaClass() const; + + /// Retrieve the function call operator associated with this + /// lambda expression. + CXXMethodDecl *getCallOperator() const; + + /// Retrieve the function template call operator associated with this + /// lambda expression. + FunctionTemplateDecl *getDependentCallOperator() const; + + /// If this is a generic lambda expression, retrieve the template + /// parameter list associated with it, or else return null. + TemplateParameterList *getTemplateParameterList() const; + + /// Get the template parameters were explicitly specified (as opposed to being + /// invented by use of an auto parameter). + ArrayRef<NamedDecl *> getExplicitTemplateParameters() const; + + /// Get the trailing requires clause, if any. + Expr *getTrailingRequiresClause() const; + + /// Whether this is a generic lambda. + bool isGenericLambda() const { return getTemplateParameterList(); } + + /// Retrieve the body of the lambda. This will be most of the time + /// a \p CompoundStmt, but can also be \p CoroutineBodyStmt wrapping + /// a \p CompoundStmt. Note that unlike functions, lambda-expressions + /// cannot have a function-try-block. + Stmt *getBody() const; + + /// Retrieve the \p CompoundStmt representing the body of the lambda. + /// This is a convenience function for callers who do not need + /// to handle node(s) which may wrap a \p CompoundStmt. + const CompoundStmt *getCompoundStmtBody() const; + CompoundStmt *getCompoundStmtBody() { + const auto *ConstThis = this; + return const_cast<CompoundStmt *>(ConstThis->getCompoundStmtBody()); + } + + /// Determine whether the lambda is mutable, meaning that any + /// captures values can be modified. + bool isMutable() const; + + /// Determine whether this lambda has an explicit parameter + /// list vs. an implicit (empty) parameter list. + bool hasExplicitParameters() const { return LambdaExprBits.ExplicitParams; } + + /// Whether this lambda had its result type explicitly specified. + bool hasExplicitResultType() const { + return LambdaExprBits.ExplicitResultType; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == LambdaExprClass; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return IntroducerRange.getBegin(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { return ClosingBrace; } + + /// Includes the captures and the body of the lambda. + child_range children(); + const_child_range children() const; +}; + +/// An expression "T()" which creates a value-initialized rvalue of type +/// T, which is a non-class type. See (C++98 [5.2.3p2]). +class CXXScalarValueInitExpr : public Expr { + friend class ASTStmtReader; + + TypeSourceInfo *TypeInfo; + +public: + /// Create an explicitly-written scalar-value initialization + /// expression. + CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo, + SourceLocation RParenLoc) + : Expr(CXXScalarValueInitExprClass, Type, VK_PRValue, OK_Ordinary), + TypeInfo(TypeInfo) { + CXXScalarValueInitExprBits.RParenLoc = RParenLoc; + setDependence(computeDependence(this)); + } + + explicit CXXScalarValueInitExpr(EmptyShell Shell) + : Expr(CXXScalarValueInitExprClass, Shell) {} + + TypeSourceInfo *getTypeSourceInfo() const { + return TypeInfo; + } + + SourceLocation getRParenLoc() const { + return CXXScalarValueInitExprBits.RParenLoc; + } + + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const { return getRParenLoc(); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXScalarValueInitExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// Represents a new-expression for memory allocation and constructor +/// calls, e.g: "new CXXNewExpr(foo)". +class CXXNewExpr final + : public Expr, + private llvm::TrailingObjects<CXXNewExpr, Stmt *, SourceRange> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + + /// Points to the allocation function used. + FunctionDecl *OperatorNew; + + /// Points to the deallocation function used in case of error. May be null. + FunctionDecl *OperatorDelete; + + /// The allocated type-source information, as written in the source. + TypeSourceInfo *AllocatedTypeInfo; + + /// Range of the entire new expression. + SourceRange Range; + + /// Source-range of a paren-delimited initializer. + SourceRange DirectInitRange; + + // CXXNewExpr is followed by several optional trailing objects. + // They are in order: + // + // * An optional "Stmt *" for the array size expression. + // Present if and ony if isArray(). + // + // * An optional "Stmt *" for the init expression. + // Present if and only if hasInitializer(). + // + // * An array of getNumPlacementArgs() "Stmt *" for the placement new + // arguments, if any. + // + // * An optional SourceRange for the range covering the parenthesized type-id + // if the allocated type was expressed as a parenthesized type-id. + // Present if and only if isParenTypeId(). + unsigned arraySizeOffset() const { return 0; } + unsigned initExprOffset() const { return arraySizeOffset() + isArray(); } + unsigned placementNewArgsOffset() const { + return initExprOffset() + hasInitializer(); + } + + unsigned numTrailingObjects(OverloadToken<Stmt *>) const { + return isArray() + hasInitializer() + getNumPlacementArgs(); + } + + unsigned numTrailingObjects(OverloadToken<SourceRange>) const { + return isParenTypeId(); + } + +public: + enum InitializationStyle { + /// New-expression has no initializer as written. + NoInit, + + /// New-expression has a C++98 paren-delimited initializer. + CallInit, + + /// New-expression has a C++11 list-initializer. + ListInit + }; + +private: + /// Build a c++ new expression. + CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, + FunctionDecl *OperatorDelete, bool ShouldPassAlignment, + bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, + SourceRange TypeIdParens, std::optional<Expr *> ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange); + + /// Build an empty c++ new expression. + CXXNewExpr(EmptyShell Empty, bool IsArray, unsigned NumPlacementArgs, + bool IsParenTypeId); + +public: + /// Create a c++ new expression. + static CXXNewExpr * + Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew, + FunctionDecl *OperatorDelete, bool ShouldPassAlignment, + bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, + SourceRange TypeIdParens, std::optional<Expr *> ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange); + + /// Create an empty c++ new expression. + static CXXNewExpr *CreateEmpty(const ASTContext &Ctx, bool IsArray, + bool HasInit, unsigned NumPlacementArgs, + bool IsParenTypeId); + + QualType getAllocatedType() const { + return getType()->castAs<PointerType>()->getPointeeType(); + } + + TypeSourceInfo *getAllocatedTypeSourceInfo() const { + return AllocatedTypeInfo; + } + + /// True if the allocation result needs to be null-checked. + /// + /// C++11 [expr.new]p13: + /// If the allocation function returns null, initialization shall + /// not be done, the deallocation function shall not be called, + /// and the value of the new-expression shall be null. + /// + /// C++ DR1748: + /// If the allocation function is a reserved placement allocation + /// function that returns null, the behavior is undefined. + /// + /// An allocation function is not allowed to return null unless it + /// has a non-throwing exception-specification. The '03 rule is + /// identical except that the definition of a non-throwing + /// exception specification is just "is it throw()?". + bool shouldNullCheckAllocation() const; + + FunctionDecl *getOperatorNew() const { return OperatorNew; } + void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } + FunctionDecl *getOperatorDelete() const { return OperatorDelete; } + void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } + + bool isArray() const { return CXXNewExprBits.IsArray; } + + /// This might return std::nullopt even if isArray() returns true, + /// since there might not be an array size expression. + /// If the result is not-None, it will never wrap a nullptr. + std::optional<Expr *> getArraySize() { + if (!isArray()) + return std::nullopt; + + if (auto *Result = + cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()])) + return Result; + + return std::nullopt; + } + + /// This might return std::nullopt even if isArray() returns true, + /// since there might not be an array size expression. + /// If the result is not-None, it will never wrap a nullptr. + std::optional<const Expr *> getArraySize() const { + if (!isArray()) + return std::nullopt; + + if (auto *Result = + cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()])) + return Result; + + return std::nullopt; + } + + unsigned getNumPlacementArgs() const { + return CXXNewExprBits.NumPlacementArgs; + } + + Expr **getPlacementArgs() { + return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>() + + placementNewArgsOffset()); + } + + Expr *getPlacementArg(unsigned I) { + assert((I < getNumPlacementArgs()) && "Index out of range!"); + return getPlacementArgs()[I]; + } + const Expr *getPlacementArg(unsigned I) const { + return const_cast<CXXNewExpr *>(this)->getPlacementArg(I); + } + + bool isParenTypeId() const { return CXXNewExprBits.IsParenTypeId; } + SourceRange getTypeIdParens() const { + return isParenTypeId() ? getTrailingObjects<SourceRange>()[0] + : SourceRange(); + } + + bool isGlobalNew() const { return CXXNewExprBits.IsGlobalNew; } + + /// Whether this new-expression has any initializer at all. + bool hasInitializer() const { + return CXXNewExprBits.StoredInitializationStyle > 0; + } + + /// The kind of initializer this new-expression has. + InitializationStyle getInitializationStyle() const { + if (CXXNewExprBits.StoredInitializationStyle == 0) + return NoInit; + return static_cast<InitializationStyle>( + CXXNewExprBits.StoredInitializationStyle - 1); + } + + /// The initializer of this new-expression. + Expr *getInitializer() { + return hasInitializer() + ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()]) + : nullptr; + } + const Expr *getInitializer() const { + return hasInitializer() + ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()]) + : nullptr; + } + + /// Returns the CXXConstructExpr from this new-expression, or null. + const CXXConstructExpr *getConstructExpr() const { + return dyn_cast_or_null<CXXConstructExpr>(getInitializer()); + } + + /// Indicates whether the required alignment should be implicitly passed to + /// the allocation function. + bool passAlignment() const { return CXXNewExprBits.ShouldPassAlignment; } + + /// Answers whether the usual array deallocation function for the + /// allocated type expects the size of the allocation as a + /// parameter. + bool doesUsualArrayDeleteWantSize() const { + return CXXNewExprBits.UsualArrayDeleteWantsSize; + } + + using arg_iterator = ExprIterator; + using const_arg_iterator = ConstExprIterator; + + llvm::iterator_range<arg_iterator> placement_arguments() { + return llvm::make_range(placement_arg_begin(), placement_arg_end()); + } + + llvm::iterator_range<const_arg_iterator> placement_arguments() const { + return llvm::make_range(placement_arg_begin(), placement_arg_end()); + } + + arg_iterator placement_arg_begin() { + return getTrailingObjects<Stmt *>() + placementNewArgsOffset(); + } + arg_iterator placement_arg_end() { + return placement_arg_begin() + getNumPlacementArgs(); + } + const_arg_iterator placement_arg_begin() const { + return getTrailingObjects<Stmt *>() + placementNewArgsOffset(); + } + const_arg_iterator placement_arg_end() const { + return placement_arg_begin() + getNumPlacementArgs(); + } + + using raw_arg_iterator = Stmt **; + + raw_arg_iterator raw_arg_begin() { return getTrailingObjects<Stmt *>(); } + raw_arg_iterator raw_arg_end() { + return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>()); + } + const_arg_iterator raw_arg_begin() const { + return getTrailingObjects<Stmt *>(); + } + const_arg_iterator raw_arg_end() const { + return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>()); + } + + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } + + SourceRange getDirectInitRange() const { return DirectInitRange; } + SourceRange getSourceRange() const { return Range; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXNewExprClass; + } + + // Iterators + child_range children() { return child_range(raw_arg_begin(), raw_arg_end()); } + + const_child_range children() const { + return const_child_range(const_cast<CXXNewExpr *>(this)->children()); + } +}; + +/// Represents a \c delete expression for memory deallocation and +/// destructor calls, e.g. "delete[] pArray". +class CXXDeleteExpr : public Expr { + friend class ASTStmtReader; + + /// Points to the operator delete overload that is used. Could be a member. + FunctionDecl *OperatorDelete = nullptr; + + /// The pointer expression to be deleted. + Stmt *Argument = nullptr; + +public: + CXXDeleteExpr(QualType Ty, bool GlobalDelete, bool ArrayForm, + bool ArrayFormAsWritten, bool UsualArrayDeleteWantsSize, + FunctionDecl *OperatorDelete, Expr *Arg, SourceLocation Loc) + : Expr(CXXDeleteExprClass, Ty, VK_PRValue, OK_Ordinary), + OperatorDelete(OperatorDelete), Argument(Arg) { + CXXDeleteExprBits.GlobalDelete = GlobalDelete; + CXXDeleteExprBits.ArrayForm = ArrayForm; + CXXDeleteExprBits.ArrayFormAsWritten = ArrayFormAsWritten; + CXXDeleteExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize; + CXXDeleteExprBits.Loc = Loc; + setDependence(computeDependence(this)); + } + + explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell) {} + + bool isGlobalDelete() const { return CXXDeleteExprBits.GlobalDelete; } + bool isArrayForm() const { return CXXDeleteExprBits.ArrayForm; } + bool isArrayFormAsWritten() const { + return CXXDeleteExprBits.ArrayFormAsWritten; + } + + /// Answers whether the usual array deallocation function for the + /// allocated type expects the size of the allocation as a + /// parameter. This can be true even if the actual deallocation + /// function that we're using doesn't want a size. + bool doesUsualArrayDeleteWantSize() const { + return CXXDeleteExprBits.UsualArrayDeleteWantsSize; + } + + FunctionDecl *getOperatorDelete() const { return OperatorDelete; } + + Expr *getArgument() { return cast<Expr>(Argument); } + const Expr *getArgument() const { return cast<Expr>(Argument); } + + /// Retrieve the type being destroyed. + /// + /// If the type being destroyed is a dependent type which may or may not + /// be a pointer, return an invalid type. + QualType getDestroyedType() const; + + SourceLocation getBeginLoc() const { return CXXDeleteExprBits.Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { + return Argument->getEndLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDeleteExprClass; + } + + // Iterators + child_range children() { return child_range(&Argument, &Argument + 1); } + + const_child_range children() const { + return const_child_range(&Argument, &Argument + 1); + } +}; + +/// Stores the type being destroyed by a pseudo-destructor expression. +class PseudoDestructorTypeStorage { + /// Either the type source information or the name of the type, if + /// it couldn't be resolved due to type-dependence. + llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type; + + /// The starting source location of the pseudo-destructor type. + SourceLocation Location; + +public: + PseudoDestructorTypeStorage() = default; + + PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc) + : Type(II), Location(Loc) {} + + PseudoDestructorTypeStorage(TypeSourceInfo *Info); + + TypeSourceInfo *getTypeSourceInfo() const { + return Type.dyn_cast<TypeSourceInfo *>(); + } + + IdentifierInfo *getIdentifier() const { + return Type.dyn_cast<IdentifierInfo *>(); + } + + SourceLocation getLocation() const { return Location; } +}; + +/// Represents a C++ pseudo-destructor (C++ [expr.pseudo]). +/// +/// A pseudo-destructor is an expression that looks like a member access to a +/// destructor of a scalar type, except that scalar types don't have +/// destructors. For example: +/// +/// \code +/// typedef int T; +/// void f(int *p) { +/// p->T::~T(); +/// } +/// \endcode +/// +/// Pseudo-destructors typically occur when instantiating templates such as: +/// +/// \code +/// template<typename T> +/// void destroy(T* ptr) { +/// ptr->T::~T(); +/// } +/// \endcode +/// +/// for scalar types. A pseudo-destructor expression has no run-time semantics +/// beyond evaluating the base expression. +class CXXPseudoDestructorExpr : public Expr { + friend class ASTStmtReader; + + /// The base expression (that is being destroyed). + Stmt *Base = nullptr; + + /// Whether the operator was an arrow ('->'); otherwise, it was a + /// period ('.'). + bool IsArrow : 1; + + /// The location of the '.' or '->' operator. + SourceLocation OperatorLoc; + + /// The nested-name-specifier that follows the operator, if present. + NestedNameSpecifierLoc QualifierLoc; + + /// The type that precedes the '::' in a qualified pseudo-destructor + /// expression. + TypeSourceInfo *ScopeType = nullptr; + + /// The location of the '::' in a qualified pseudo-destructor + /// expression. + SourceLocation ColonColonLoc; + + /// The location of the '~'. + SourceLocation TildeLoc; + + /// The type being destroyed, or its name if we were unable to + /// resolve the name. + PseudoDestructorTypeStorage DestroyedType; + +public: + CXXPseudoDestructorExpr(const ASTContext &Context, + Expr *Base, bool isArrow, SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, + TypeSourceInfo *ScopeType, + SourceLocation ColonColonLoc, + SourceLocation TildeLoc, + PseudoDestructorTypeStorage DestroyedType); + + explicit CXXPseudoDestructorExpr(EmptyShell Shell) + : Expr(CXXPseudoDestructorExprClass, Shell), IsArrow(false) {} + + Expr *getBase() const { return cast<Expr>(Base); } + + /// Determines whether this member expression actually had + /// a C++ nested-name-specifier prior to the name of the member, e.g., + /// x->Base::foo. + bool hasQualifier() const { return QualifierLoc.hasQualifier(); } + + /// Retrieves the nested-name-specifier that qualifies the type name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// If the member name was qualified, retrieves the + /// nested-name-specifier that precedes the member name. Otherwise, returns + /// null. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + + /// Determine whether this pseudo-destructor expression was written + /// using an '->' (otherwise, it used a '.'). + bool isArrow() const { return IsArrow; } + + /// Retrieve the location of the '.' or '->' operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + + /// Retrieve the scope type in a qualified pseudo-destructor + /// expression. + /// + /// Pseudo-destructor expressions can have extra qualification within them + /// that is not part of the nested-name-specifier, e.g., \c p->T::~T(). + /// Here, if the object type of the expression is (or may be) a scalar type, + /// \p T may also be a scalar type and, therefore, cannot be part of a + /// nested-name-specifier. It is stored as the "scope type" of the pseudo- + /// destructor expression. + TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; } + + /// Retrieve the location of the '::' in a qualified pseudo-destructor + /// expression. + SourceLocation getColonColonLoc() const { return ColonColonLoc; } + + /// Retrieve the location of the '~'. + SourceLocation getTildeLoc() const { return TildeLoc; } + + /// Retrieve the source location information for the type + /// being destroyed. + /// + /// This type-source information is available for non-dependent + /// pseudo-destructor expressions and some dependent pseudo-destructor + /// expressions. Returns null if we only have the identifier for a + /// dependent pseudo-destructor expression. + TypeSourceInfo *getDestroyedTypeInfo() const { + return DestroyedType.getTypeSourceInfo(); + } + + /// In a dependent pseudo-destructor expression for which we do not + /// have full type information on the destroyed type, provides the name + /// of the destroyed type. + IdentifierInfo *getDestroyedTypeIdentifier() const { + return DestroyedType.getIdentifier(); + } + + /// Retrieve the type being destroyed. + QualType getDestroyedType() const; + + /// Retrieve the starting location of the type being destroyed. + SourceLocation getDestroyedTypeLoc() const { + return DestroyedType.getLocation(); + } + + /// Set the name of destroyed type for a dependent pseudo-destructor + /// expression. + void setDestroyedType(IdentifierInfo *II, SourceLocation Loc) { + DestroyedType = PseudoDestructorTypeStorage(II, Loc); + } + + /// Set the destroyed type. + void setDestroyedType(TypeSourceInfo *Info) { + DestroyedType = PseudoDestructorTypeStorage(Info); + } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return Base->getBeginLoc(); + } + SourceLocation getEndLoc() const LLVM_READONLY; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXPseudoDestructorExprClass; + } + + // Iterators + child_range children() { return child_range(&Base, &Base + 1); } + + const_child_range children() const { + return const_child_range(&Base, &Base + 1); + } +}; + +/// A type trait used in the implementation of various C++11 and +/// Library TR1 trait templates. +/// +/// \code +/// __is_pod(int) == true +/// __is_enum(std::string) == false +/// __is_trivially_constructible(vector<int>, int*, int*) +/// \endcode +class TypeTraitExpr final + : public Expr, + private llvm::TrailingObjects<TypeTraitExpr, TypeSourceInfo *> { + /// The location of the type trait keyword. + SourceLocation Loc; + + /// The location of the closing parenthesis. + SourceLocation RParenLoc; + + // Note: The TypeSourceInfos for the arguments are allocated after the + // TypeTraitExpr. + + TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, + ArrayRef<TypeSourceInfo *> Args, + SourceLocation RParenLoc, + bool Value); + + TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) {} + + size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const { + return getNumArgs(); + } + +public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + + /// Create a new type trait expression. + static TypeTraitExpr *Create(const ASTContext &C, QualType T, + SourceLocation Loc, TypeTrait Kind, + ArrayRef<TypeSourceInfo *> Args, + SourceLocation RParenLoc, + bool Value); + + static TypeTraitExpr *CreateDeserialized(const ASTContext &C, + unsigned NumArgs); + + /// Determine which type trait this expression uses. + TypeTrait getTrait() const { + return static_cast<TypeTrait>(TypeTraitExprBits.Kind); + } + + bool getValue() const { + assert(!isValueDependent()); + return TypeTraitExprBits.Value; + } + + /// Determine the number of arguments to this type trait. + unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; } + + /// Retrieve the Ith argument. + TypeSourceInfo *getArg(unsigned I) const { + assert(I < getNumArgs() && "Argument out-of-range"); + return getArgs()[I]; + } + + /// Retrieve the argument types. + ArrayRef<TypeSourceInfo *> getArgs() const { + return llvm::ArrayRef(getTrailingObjects<TypeSourceInfo *>(), getNumArgs()); + } + + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == TypeTraitExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// An Embarcadero array type trait, as used in the implementation of +/// __array_rank and __array_extent. +/// +/// Example: +/// \code +/// __array_rank(int[10][20]) == 2 +/// __array_extent(int, 1) == 20 +/// \endcode +class ArrayTypeTraitExpr : public Expr { + /// The trait. An ArrayTypeTrait enum in MSVC compat unsigned. + unsigned ATT : 2; + + /// The value of the type trait. Unspecified if dependent. + uint64_t Value = 0; + + /// The array dimension being queried, or -1 if not used. + Expr *Dimension; + + /// The location of the type trait keyword. + SourceLocation Loc; + + /// The location of the closing paren. + SourceLocation RParen; + + /// The type being queried. + TypeSourceInfo *QueriedType = nullptr; + +public: + friend class ASTStmtReader; + + ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att, + TypeSourceInfo *queried, uint64_t value, Expr *dimension, + SourceLocation rparen, QualType ty) + : Expr(ArrayTypeTraitExprClass, ty, VK_PRValue, OK_Ordinary), ATT(att), + Value(value), Dimension(dimension), Loc(loc), RParen(rparen), + QueriedType(queried) { + assert(att <= ATT_Last && "invalid enum value!"); + assert(static_cast<unsigned>(att) == ATT && "ATT overflow!"); + setDependence(computeDependence(this)); + } + + explicit ArrayTypeTraitExpr(EmptyShell Empty) + : Expr(ArrayTypeTraitExprClass, Empty), ATT(0) {} + + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParen; } + + ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); } + + QualType getQueriedType() const { return QueriedType->getType(); } + + TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } + + uint64_t getValue() const { assert(!isTypeDependent()); return Value; } + + Expr *getDimensionExpression() const { return Dimension; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ArrayTypeTraitExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// An expression trait intrinsic. +/// +/// Example: +/// \code +/// __is_lvalue_expr(std::cout) == true +/// __is_lvalue_expr(1) == false +/// \endcode +class ExpressionTraitExpr : public Expr { + /// The trait. A ExpressionTrait enum in MSVC compatible unsigned. + unsigned ET : 31; + + /// The value of the type trait. Unspecified if dependent. + unsigned Value : 1; + + /// The location of the type trait keyword. + SourceLocation Loc; + + /// The location of the closing paren. + SourceLocation RParen; + + /// The expression being queried. + Expr* QueriedExpression = nullptr; + +public: + friend class ASTStmtReader; + + ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, Expr *queried, + bool value, SourceLocation rparen, QualType resultType) + : Expr(ExpressionTraitExprClass, resultType, VK_PRValue, OK_Ordinary), + ET(et), Value(value), Loc(loc), RParen(rparen), + QueriedExpression(queried) { + assert(et <= ET_Last && "invalid enum value!"); + assert(static_cast<unsigned>(et) == ET && "ET overflow!"); + setDependence(computeDependence(this)); + } + + explicit ExpressionTraitExpr(EmptyShell Empty) + : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false) {} + + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParen; } + + ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); } + + Expr *getQueriedExpression() const { return QueriedExpression; } + + bool getValue() const { return Value; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ExpressionTraitExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// A reference to an overloaded function set, either an +/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr. +class OverloadExpr : public Expr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + + /// The common name of these declarations. + DeclarationNameInfo NameInfo; + + /// The nested-name-specifier that qualifies the name, if any. + NestedNameSpecifierLoc QualifierLoc; + +protected: + OverloadExpr(StmtClass SC, const ASTContext &Context, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool KnownDependent, bool KnownInstantiationDependent, + bool KnownContainsUnexpandedParameterPack); + + OverloadExpr(StmtClass SC, EmptyShell Empty, unsigned NumResults, + bool HasTemplateKWAndArgsInfo); + + /// Return the results. Defined after UnresolvedMemberExpr. + inline DeclAccessPair *getTrailingResults(); + const DeclAccessPair *getTrailingResults() const { + return const_cast<OverloadExpr *>(this)->getTrailingResults(); + } + + /// Return the optional template keyword and arguments info. + /// Defined after UnresolvedMemberExpr. + inline ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo(); + const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const { + return const_cast<OverloadExpr *>(this) + ->getTrailingASTTemplateKWAndArgsInfo(); + } + + /// Return the optional template arguments. Defined after + /// UnresolvedMemberExpr. + inline TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); + const TemplateArgumentLoc *getTrailingTemplateArgumentLoc() const { + return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc(); + } + + bool hasTemplateKWAndArgsInfo() const { + return OverloadExprBits.HasTemplateKWAndArgsInfo; + } + +public: + struct FindResult { + OverloadExpr *Expression; + bool IsAddressOfOperand; + bool HasFormOfMemberPointer; + }; + + /// Finds the overloaded expression in the given expression \p E of + /// OverloadTy. + /// + /// \return the expression (which must be there) and true if it has + /// the particular form of a member pointer expression + static FindResult find(Expr *E) { + assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload)); + + FindResult Result; + + E = E->IgnoreParens(); + if (isa<UnaryOperator>(E)) { + assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf); + E = cast<UnaryOperator>(E)->getSubExpr(); + auto *Ovl = cast<OverloadExpr>(E->IgnoreParens()); + + Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier()); + Result.IsAddressOfOperand = true; + Result.Expression = Ovl; + } else { + Result.HasFormOfMemberPointer = false; + Result.IsAddressOfOperand = false; + Result.Expression = cast<OverloadExpr>(E); + } + + return Result; + } + + /// Gets the naming class of this lookup, if any. + /// Defined after UnresolvedMemberExpr. + inline CXXRecordDecl *getNamingClass(); + const CXXRecordDecl *getNamingClass() const { + return const_cast<OverloadExpr *>(this)->getNamingClass(); + } + + using decls_iterator = UnresolvedSetImpl::iterator; + + decls_iterator decls_begin() const { + return UnresolvedSetIterator(getTrailingResults()); + } + decls_iterator decls_end() const { + return UnresolvedSetIterator(getTrailingResults() + getNumDecls()); + } + llvm::iterator_range<decls_iterator> decls() const { + return llvm::make_range(decls_begin(), decls_end()); + } + + /// Gets the number of declarations in the unresolved set. + unsigned getNumDecls() const { return OverloadExprBits.NumResults; } + + /// Gets the full name info. + const DeclarationNameInfo &getNameInfo() const { return NameInfo; } + + /// Gets the name looked up. + DeclarationName getName() const { return NameInfo.getName(); } + + /// Gets the location of the name. + SourceLocation getNameLoc() const { return NameInfo.getLoc(); } + + /// Fetches the nested-name qualifier, if one was given. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + + /// Fetches the nested-name qualifier with source-location + /// information, if one was given. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// Retrieve the location of the template keyword preceding + /// this name, if any. + SourceLocation getTemplateKeywordLoc() const { + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); + return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc; + } + + /// Retrieve the location of the left angle bracket starting the + /// explicit template argument list following the name, if any. + SourceLocation getLAngleLoc() const { + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); + return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc; + } + + /// Retrieve the location of the right angle bracket ending the + /// explicit template argument list following the name, if any. + SourceLocation getRAngleLoc() const { + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); + return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc; + } + + /// Determines whether the name was preceded by the template keyword. + bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } + + /// Determines whether this expression had explicit template arguments. + bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } + + TemplateArgumentLoc const *getTemplateArgs() const { + if (!hasExplicitTemplateArgs()) + return nullptr; + return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc(); + } + + unsigned getNumTemplateArgs() const { + if (!hasExplicitTemplateArgs()) + return 0; + + return getTrailingASTTemplateKWAndArgsInfo()->NumTemplateArgs; + } + + ArrayRef<TemplateArgumentLoc> template_arguments() const { + return {getTemplateArgs(), getNumTemplateArgs()}; + } + + /// Copies the template arguments into the given structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + if (hasExplicitTemplateArgs()) + getTrailingASTTemplateKWAndArgsInfo()->copyInto(getTemplateArgs(), List); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedLookupExprClass || + T->getStmtClass() == UnresolvedMemberExprClass; + } +}; + +/// A reference to a name which we were able to look up during +/// parsing but could not resolve to a specific declaration. +/// +/// This arises in several ways: +/// * we might be waiting for argument-dependent lookup; +/// * the name might resolve to an overloaded function; +/// and eventually: +/// * the lookup might have included a function template. +/// +/// These never include UnresolvedUsingValueDecls, which are always class +/// members and therefore appear only in UnresolvedMemberLookupExprs. +class UnresolvedLookupExpr final + : public OverloadExpr, + private llvm::TrailingObjects<UnresolvedLookupExpr, DeclAccessPair, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { + friend class ASTStmtReader; + friend class OverloadExpr; + friend TrailingObjects; + + /// The naming class (C++ [class.access.base]p5) of the lookup, if + /// any. This can generally be recalculated from the context chain, + /// but that can be fairly expensive for unqualified lookups. + CXXRecordDecl *NamingClass; + + // UnresolvedLookupExpr is followed by several trailing objects. + // They are in order: + // + // * An array of getNumResults() DeclAccessPair for the results. These are + // undesugared, which is to say, they may include UsingShadowDecls. + // Access is relative to the naming class. + // + // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified + // template keyword and arguments. Present if and only if + // hasTemplateKWAndArgsInfo(). + // + // * An array of getNumTemplateArgs() TemplateArgumentLoc containing + // location information for the explicitly specified template arguments. + + UnresolvedLookupExpr(const ASTContext &Context, CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, + bool Overloaded, + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); + + UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults, + bool HasTemplateKWAndArgsInfo); + + unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const { + return getNumDecls(); + } + + unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo(); + } + +public: + static UnresolvedLookupExpr * + Create(const ASTContext &Context, CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); + + static UnresolvedLookupExpr * + Create(const ASTContext &Context, CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, + const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, + UnresolvedSetIterator End); + + static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context, + unsigned NumResults, + bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs); + + /// True if this declaration should be extended by + /// argument-dependent lookup. + bool requiresADL() const { return UnresolvedLookupExprBits.RequiresADL; } + + /// True if this lookup is overloaded. + bool isOverloaded() const { return UnresolvedLookupExprBits.Overloaded; } + + /// Gets the 'naming class' (in the sense of C++0x + /// [class.access.base]p5) of the lookup. This is the scope + /// that was looked in to find these results. + CXXRecordDecl *getNamingClass() { return NamingClass; } + const CXXRecordDecl *getNamingClass() const { return NamingClass; } + + SourceLocation getBeginLoc() const LLVM_READONLY { + if (NestedNameSpecifierLoc l = getQualifierLoc()) + return l.getBeginLoc(); + return getNameInfo().getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + if (hasExplicitTemplateArgs()) + return getRAngleLoc(); + return getNameInfo().getEndLoc(); + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedLookupExprClass; + } +}; + +/// A qualified reference to a name whose declaration cannot +/// yet be resolved. +/// +/// DependentScopeDeclRefExpr is similar to DeclRefExpr in that +/// it expresses a reference to a declaration such as +/// X<T>::value. The difference, however, is that an +/// DependentScopeDeclRefExpr node is used only within C++ templates when +/// the qualification (e.g., X<T>::) refers to a dependent type. In +/// this case, X<T>::value cannot resolve to a declaration because the +/// declaration will differ from one instantiation of X<T> to the +/// next. Therefore, DependentScopeDeclRefExpr keeps track of the +/// qualifier (X<T>::) and the name of the entity being referenced +/// ("value"). Such expressions will instantiate to a DeclRefExpr once the +/// declaration can be found. +class DependentScopeDeclRefExpr final + : public Expr, + private llvm::TrailingObjects<DependentScopeDeclRefExpr, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + + /// The nested-name-specifier that qualifies this unresolved + /// declaration name. + NestedNameSpecifierLoc QualifierLoc; + + /// The name of the entity we will be referencing. + DeclarationNameInfo NameInfo; + + DependentScopeDeclRefExpr(QualType Ty, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *Args); + + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo(); + } + + bool hasTemplateKWAndArgsInfo() const { + return DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo; + } + +public: + static DependentScopeDeclRefExpr * + Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs); + + static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &Context, + bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs); + + /// Retrieve the name that this expression refers to. + const DeclarationNameInfo &getNameInfo() const { return NameInfo; } + + /// Retrieve the name that this expression refers to. + DeclarationName getDeclName() const { return NameInfo.getName(); } + + /// Retrieve the location of the name within the expression. + /// + /// For example, in "X<T>::value" this is the location of "value". + SourceLocation getLocation() const { return NameInfo.getLoc(); } + + /// Retrieve the nested-name-specifier that qualifies the + /// name, with source location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// Retrieve the nested-name-specifier that qualifies this + /// declaration. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + + /// Retrieve the location of the template keyword preceding + /// this name, if any. + SourceLocation getTemplateKeywordLoc() const { + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; + } + + /// Retrieve the location of the left angle bracket starting the + /// explicit template argument list following the name, if any. + SourceLocation getLAngleLoc() const { + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; + } + + /// Retrieve the location of the right angle bracket ending the + /// explicit template argument list following the name, if any. + SourceLocation getRAngleLoc() const { + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; + } + + /// Determines whether the name was preceded by the template keyword. + bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } + + /// Determines whether this lookup had explicit template arguments. + bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } + + /// Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + if (hasExplicitTemplateArgs()) + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( + getTrailingObjects<TemplateArgumentLoc>(), List); + } + + TemplateArgumentLoc const *getTemplateArgs() const { + if (!hasExplicitTemplateArgs()) + return nullptr; + + return getTrailingObjects<TemplateArgumentLoc>(); + } + + unsigned getNumTemplateArgs() const { + if (!hasExplicitTemplateArgs()) + return 0; + + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; + } + + ArrayRef<TemplateArgumentLoc> template_arguments() const { + return {getTemplateArgs(), getNumTemplateArgs()}; + } + + /// Note: getBeginLoc() is the start of the whole DependentScopeDeclRefExpr, + /// and differs from getLocation().getStart(). + SourceLocation getBeginLoc() const LLVM_READONLY { + return QualifierLoc.getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + if (hasExplicitTemplateArgs()) + return getRAngleLoc(); + return getLocation(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DependentScopeDeclRefExprClass; + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// Represents an expression -- generally a full-expression -- that +/// introduces cleanups to be run at the end of the sub-expression's +/// evaluation. The most common source of expression-introduced +/// cleanups is temporary objects in C++, but several other kinds of +/// expressions can create cleanups, including basically every +/// call in ARC that returns an Objective-C pointer. +/// +/// This expression also tracks whether the sub-expression contains a +/// potentially-evaluated block literal. The lifetime of a block +/// literal is the extent of the enclosing scope. +class ExprWithCleanups final + : public FullExpr, + private llvm::TrailingObjects< + ExprWithCleanups, + llvm::PointerUnion<BlockDecl *, CompoundLiteralExpr *>> { +public: + /// The type of objects that are kept in the cleanup. + /// It's useful to remember the set of blocks and block-scoped compound + /// literals; we could also remember the set of temporaries, but there's + /// currently no need. + using CleanupObject = llvm::PointerUnion<BlockDecl *, CompoundLiteralExpr *>; + +private: + friend class ASTStmtReader; + friend TrailingObjects; + + ExprWithCleanups(EmptyShell, unsigned NumObjects); + ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects, + ArrayRef<CleanupObject> Objects); + +public: + static ExprWithCleanups *Create(const ASTContext &C, EmptyShell empty, + unsigned numObjects); + + static ExprWithCleanups *Create(const ASTContext &C, Expr *subexpr, + bool CleanupsHaveSideEffects, + ArrayRef<CleanupObject> objects); + + ArrayRef<CleanupObject> getObjects() const { + return llvm::ArrayRef(getTrailingObjects<CleanupObject>(), getNumObjects()); + } + + unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; } + + CleanupObject getObject(unsigned i) const { + assert(i < getNumObjects() && "Index out of range"); + return getObjects()[i]; + } + + bool cleanupsHaveSideEffects() const { + return ExprWithCleanupsBits.CleanupsHaveSideEffects; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return SubExpr->getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + return SubExpr->getEndLoc(); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Stmt *T) { + return T->getStmtClass() == ExprWithCleanupsClass; + } + + // Iterators + child_range children() { return child_range(&SubExpr, &SubExpr + 1); } + + const_child_range children() const { + return const_child_range(&SubExpr, &SubExpr + 1); + } +}; + +/// Describes an explicit type conversion that uses functional +/// notion but could not be resolved because one or more arguments are +/// type-dependent. +/// +/// The explicit type conversions expressed by +/// CXXUnresolvedConstructExpr have the form <tt>T(a1, a2, ..., aN)</tt>, +/// where \c T is some type and \c a1, \c a2, ..., \c aN are values, and +/// either \c T is a dependent type or one or more of the <tt>a</tt>'s is +/// type-dependent. For example, this would occur in a template such +/// as: +/// +/// \code +/// template<typename T, typename A1> +/// inline T make_a(const A1& a1) { +/// return T(a1); +/// } +/// \endcode +/// +/// When the returned expression is instantiated, it may resolve to a +/// constructor call, conversion function call, or some kind of type +/// conversion. +class CXXUnresolvedConstructExpr final + : public Expr, + private llvm::TrailingObjects<CXXUnresolvedConstructExpr, Expr *> { + friend class ASTStmtReader; + friend TrailingObjects; + + /// The type being constructed. + TypeSourceInfo *TSI; + + /// The location of the left parentheses ('('). + SourceLocation LParenLoc; + + /// The location of the right parentheses (')'). + SourceLocation RParenLoc; + + CXXUnresolvedConstructExpr(QualType T, TypeSourceInfo *TSI, + SourceLocation LParenLoc, ArrayRef<Expr *> Args, + SourceLocation RParenLoc); + + CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) + : Expr(CXXUnresolvedConstructExprClass, Empty), TSI(nullptr) { + CXXUnresolvedConstructExprBits.NumArgs = NumArgs; + } + +public: + static CXXUnresolvedConstructExpr *Create(const ASTContext &Context, + QualType T, TypeSourceInfo *TSI, + SourceLocation LParenLoc, + ArrayRef<Expr *> Args, + SourceLocation RParenLoc); + + static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &Context, + unsigned NumArgs); + + /// Retrieve the type that is being constructed, as specified + /// in the source code. + QualType getTypeAsWritten() const { return TSI->getType(); } + + /// Retrieve the type source information for the type being + /// constructed. + TypeSourceInfo *getTypeSourceInfo() const { return TSI; } + + /// Retrieve the location of the left parentheses ('(') that + /// precedes the argument list. + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + + /// Retrieve the location of the right parentheses (')') that + /// follows the argument list. + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + /// Determine whether this expression models list-initialization. + /// If so, there will be exactly one subexpression, which will be + /// an InitListExpr. + bool isListInitialization() const { return LParenLoc.isInvalid(); } + + /// Retrieve the number of arguments. + unsigned getNumArgs() const { return CXXUnresolvedConstructExprBits.NumArgs; } + + using arg_iterator = Expr **; + using arg_range = llvm::iterator_range<arg_iterator>; + + arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); } + arg_iterator arg_end() { return arg_begin() + getNumArgs(); } + arg_range arguments() { return arg_range(arg_begin(), arg_end()); } + + using const_arg_iterator = const Expr* const *; + using const_arg_range = llvm::iterator_range<const_arg_iterator>; + + const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); } + const_arg_iterator arg_end() const { return arg_begin() + getNumArgs(); } + const_arg_range arguments() const { + return const_arg_range(arg_begin(), arg_end()); + } + + Expr *getArg(unsigned I) { + assert(I < getNumArgs() && "Argument index out-of-range"); + return arg_begin()[I]; + } + + const Expr *getArg(unsigned I) const { + assert(I < getNumArgs() && "Argument index out-of-range"); + return arg_begin()[I]; + } + + void setArg(unsigned I, Expr *E) { + assert(I < getNumArgs() && "Argument index out-of-range"); + arg_begin()[I] = E; + } + + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY { + if (!RParenLoc.isValid() && getNumArgs() > 0) + return getArg(getNumArgs() - 1)->getEndLoc(); + return RParenLoc; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXUnresolvedConstructExprClass; + } + + // Iterators + child_range children() { + auto **begin = reinterpret_cast<Stmt **>(arg_begin()); + return child_range(begin, begin + getNumArgs()); + } + + const_child_range children() const { + auto **begin = reinterpret_cast<Stmt **>( + const_cast<CXXUnresolvedConstructExpr *>(this)->arg_begin()); + return const_child_range(begin, begin + getNumArgs()); + } +}; + +/// Represents a C++ member access expression where the actual +/// member referenced could not be resolved because the base +/// expression or the member name was dependent. +/// +/// Like UnresolvedMemberExprs, these can be either implicit or +/// explicit accesses. It is only possible to get one of these with +/// an implicit access if a qualifier is provided. +class CXXDependentScopeMemberExpr final + : public Expr, + private llvm::TrailingObjects<CXXDependentScopeMemberExpr, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc, NamedDecl *> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + + /// The expression for the base pointer or class reference, + /// e.g., the \c x in x.f. Can be null in implicit accesses. + Stmt *Base; + + /// The type of the base expression. Never null, even for + /// implicit accesses. + QualType BaseType; + + /// The nested-name-specifier that precedes the member name, if any. + /// FIXME: This could be in principle store as a trailing object. + /// However the performance impact of doing so should be investigated first. + NestedNameSpecifierLoc QualifierLoc; + + /// The member to which this member expression refers, which + /// can be name, overloaded operator, or destructor. + /// + /// FIXME: could also be a template-id + DeclarationNameInfo MemberNameInfo; + + // CXXDependentScopeMemberExpr is followed by several trailing objects, + // some of which optional. They are in order: + // + // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified + // template keyword and arguments. Present if and only if + // hasTemplateKWAndArgsInfo(). + // + // * An array of getNumTemplateArgs() TemplateArgumentLoc containing location + // information for the explicitly specified template arguments. + // + // * An optional NamedDecl *. In a qualified member access expression such + // as t->Base::f, this member stores the resolves of name lookup in the + // context of the member access expression, to be used at instantiation + // time. Present if and only if hasFirstQualifierFoundInScope(). + + bool hasTemplateKWAndArgsInfo() const { + return CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo; + } + + bool hasFirstQualifierFoundInScope() const { + return CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope; + } + + unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo(); + } + + unsigned numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const { + return getNumTemplateArgs(); + } + + unsigned numTrailingObjects(OverloadToken<NamedDecl *>) const { + return hasFirstQualifierFoundInScope(); + } + + CXXDependentScopeMemberExpr(const ASTContext &Ctx, Expr *Base, + QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierFoundInScope, + DeclarationNameInfo MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs); + + CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasTemplateKWAndArgsInfo, + bool HasFirstQualifierFoundInScope); + +public: + static CXXDependentScopeMemberExpr * + Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, + DeclarationNameInfo MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs); + + static CXXDependentScopeMemberExpr * + CreateEmpty(const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope); + + /// True if this is an implicit access, i.e. one in which the + /// member being accessed was not written in the source. The source + /// location of the operator is invalid in this case. + bool isImplicitAccess() const { + if (!Base) + return true; + return cast<Expr>(Base)->isImplicitCXXThis(); + } + + /// Retrieve the base object of this member expressions, + /// e.g., the \c x in \c x.m. + Expr *getBase() const { + assert(!isImplicitAccess()); + return cast<Expr>(Base); + } + + QualType getBaseType() const { return BaseType; } + + /// Determine whether this member expression used the '->' + /// operator; otherwise, it used the '.' operator. + bool isArrow() const { return CXXDependentScopeMemberExprBits.IsArrow; } + + /// Retrieve the location of the '->' or '.' operator. + SourceLocation getOperatorLoc() const { + return CXXDependentScopeMemberExprBits.OperatorLoc; + } + + /// Retrieve the nested-name-specifier that qualifies the member name. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + + /// Retrieve the nested-name-specifier that qualifies the member + /// name, with source location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// Retrieve the first part of the nested-name-specifier that was + /// found in the scope of the member access expression when the member access + /// was initially parsed. + /// + /// This function only returns a useful result when member access expression + /// uses a qualified member name, e.g., "x.Base::f". Here, the declaration + /// returned by this function describes what was found by unqualified name + /// lookup for the identifier "Base" within the scope of the member access + /// expression itself. At template instantiation time, this information is + /// combined with the results of name lookup into the type of the object + /// expression itself (the class type of x). + NamedDecl *getFirstQualifierFoundInScope() const { + if (!hasFirstQualifierFoundInScope()) + return nullptr; + return *getTrailingObjects<NamedDecl *>(); + } + + /// Retrieve the name of the member that this expression refers to. + const DeclarationNameInfo &getMemberNameInfo() const { + return MemberNameInfo; + } + + /// Retrieve the name of the member that this expression refers to. + DeclarationName getMember() const { return MemberNameInfo.getName(); } + + // Retrieve the location of the name of the member that this + // expression refers to. + SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); } + + /// Retrieve the location of the template keyword preceding the + /// member name, if any. + SourceLocation getTemplateKeywordLoc() const { + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; + } + + /// Retrieve the location of the left angle bracket starting the + /// explicit template argument list following the member name, if any. + SourceLocation getLAngleLoc() const { + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; + } + + /// Retrieve the location of the right angle bracket ending the + /// explicit template argument list following the member name, if any. + SourceLocation getRAngleLoc() const { + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; + } + + /// Determines whether the member name was preceded by the template keyword. + bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } + + /// Determines whether this member expression actually had a C++ + /// template argument list explicitly specified, e.g., x.f<int>. + bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } + + /// Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + if (hasExplicitTemplateArgs()) + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( + getTrailingObjects<TemplateArgumentLoc>(), List); + } + + /// Retrieve the template arguments provided as part of this + /// template-id. + const TemplateArgumentLoc *getTemplateArgs() const { + if (!hasExplicitTemplateArgs()) + return nullptr; + + return getTrailingObjects<TemplateArgumentLoc>(); + } + + /// Retrieve the number of template arguments provided as part of this + /// template-id. + unsigned getNumTemplateArgs() const { + if (!hasExplicitTemplateArgs()) + return 0; + + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; + } + + ArrayRef<TemplateArgumentLoc> template_arguments() const { + return {getTemplateArgs(), getNumTemplateArgs()}; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { + if (!isImplicitAccess()) + return Base->getBeginLoc(); + if (getQualifier()) + return getQualifierLoc().getBeginLoc(); + return MemberNameInfo.getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + if (hasExplicitTemplateArgs()) + return getRAngleLoc(); + return MemberNameInfo.getEndLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXDependentScopeMemberExprClass; + } + + // Iterators + child_range children() { + if (isImplicitAccess()) + return child_range(child_iterator(), child_iterator()); + return child_range(&Base, &Base + 1); + } + + const_child_range children() const { + if (isImplicitAccess()) + return const_child_range(const_child_iterator(), const_child_iterator()); + return const_child_range(&Base, &Base + 1); + } +}; + +/// Represents a C++ member access expression for which lookup +/// produced a set of overloaded functions. +/// +/// The member access may be explicit or implicit: +/// \code +/// struct A { +/// int a, b; +/// int explicitAccess() { return this->a + this->A::b; } +/// int implicitAccess() { return a + A::b; } +/// }; +/// \endcode +/// +/// In the final AST, an explicit access always becomes a MemberExpr. +/// An implicit access may become either a MemberExpr or a +/// DeclRefExpr, depending on whether the member is static. +class UnresolvedMemberExpr final + : public OverloadExpr, + private llvm::TrailingObjects<UnresolvedMemberExpr, DeclAccessPair, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { + friend class ASTStmtReader; + friend class OverloadExpr; + friend TrailingObjects; + + /// The expression for the base pointer or class reference, + /// e.g., the \c x in x.f. + /// + /// This can be null if this is an 'unbased' member expression. + Stmt *Base; + + /// The type of the base expression; never null. + QualType BaseType; + + /// The location of the '->' or '.' operator. + SourceLocation OperatorLoc; + + // UnresolvedMemberExpr is followed by several trailing objects. + // They are in order: + // + // * An array of getNumResults() DeclAccessPair for the results. These are + // undesugared, which is to say, they may include UsingShadowDecls. + // Access is relative to the naming class. + // + // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified + // template keyword and arguments. Present if and only if + // hasTemplateKWAndArgsInfo(). + // + // * An array of getNumTemplateArgs() TemplateArgumentLoc containing + // location information for the explicitly specified template arguments. + + UnresolvedMemberExpr(const ASTContext &Context, bool HasUnresolvedUsing, + Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + const DeclarationNameInfo &MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); + + UnresolvedMemberExpr(EmptyShell Empty, unsigned NumResults, + bool HasTemplateKWAndArgsInfo); + + unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const { + return getNumDecls(); + } + + unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo(); + } + +public: + static UnresolvedMemberExpr * + Create(const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base, + QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); + + static UnresolvedMemberExpr *CreateEmpty(const ASTContext &Context, + unsigned NumResults, + bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs); + + /// True if this is an implicit access, i.e., one in which the + /// member being accessed was not written in the source. + /// + /// The source location of the operator is invalid in this case. + bool isImplicitAccess() const; + + /// Retrieve the base object of this member expressions, + /// e.g., the \c x in \c x.m. + Expr *getBase() { + assert(!isImplicitAccess()); + return cast<Expr>(Base); + } + const Expr *getBase() const { + assert(!isImplicitAccess()); + return cast<Expr>(Base); + } + + QualType getBaseType() const { return BaseType; } + + /// Determine whether the lookup results contain an unresolved using + /// declaration. + bool hasUnresolvedUsing() const { + return UnresolvedMemberExprBits.HasUnresolvedUsing; + } + + /// Determine whether this member expression used the '->' + /// operator; otherwise, it used the '.' operator. + bool isArrow() const { return UnresolvedMemberExprBits.IsArrow; } + + /// Retrieve the location of the '->' or '.' operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + + /// Retrieve the naming class of this lookup. + CXXRecordDecl *getNamingClass(); + const CXXRecordDecl *getNamingClass() const { + return const_cast<UnresolvedMemberExpr *>(this)->getNamingClass(); + } + + /// Retrieve the full name info for the member that this expression + /// refers to. + const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); } + + /// Retrieve the name of the member that this expression refers to. + DeclarationName getMemberName() const { return getName(); } + + /// Retrieve the location of the name of the member that this + /// expression refers to. + SourceLocation getMemberLoc() const { return getNameLoc(); } + + /// Return the preferred location (the member name) for the arrow when + /// diagnosing a problem with this expression. + SourceLocation getExprLoc() const LLVM_READONLY { return getMemberLoc(); } + + SourceLocation getBeginLoc() const LLVM_READONLY { + if (!isImplicitAccess()) + return Base->getBeginLoc(); + if (NestedNameSpecifierLoc l = getQualifierLoc()) + return l.getBeginLoc(); + return getMemberNameInfo().getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + if (hasExplicitTemplateArgs()) + return getRAngleLoc(); + return getMemberNameInfo().getEndLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedMemberExprClass; + } + + // Iterators + child_range children() { + if (isImplicitAccess()) + return child_range(child_iterator(), child_iterator()); + return child_range(&Base, &Base + 1); + } + + const_child_range children() const { + if (isImplicitAccess()) + return const_child_range(const_child_iterator(), const_child_iterator()); + return const_child_range(&Base, &Base + 1); + } +}; + +DeclAccessPair *OverloadExpr::getTrailingResults() { + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getTrailingObjects<DeclAccessPair>(); + return cast<UnresolvedMemberExpr>(this)->getTrailingObjects<DeclAccessPair>(); +} + +ASTTemplateKWAndArgsInfo *OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() { + if (!hasTemplateKWAndArgsInfo()) + return nullptr; + + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); + return cast<UnresolvedMemberExpr>(this) + ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); +} + +TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getTrailingObjects<TemplateArgumentLoc>(); + return cast<UnresolvedMemberExpr>(this) + ->getTrailingObjects<TemplateArgumentLoc>(); +} + +CXXRecordDecl *OverloadExpr::getNamingClass() { + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getNamingClass(); + return cast<UnresolvedMemberExpr>(this)->getNamingClass(); +} + +/// Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]). +/// +/// The noexcept expression tests whether a given expression might throw. Its +/// result is a boolean constant. +class CXXNoexceptExpr : public Expr { + friend class ASTStmtReader; + + Stmt *Operand; + SourceRange Range; + +public: + CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val, + SourceLocation Keyword, SourceLocation RParen) + : Expr(CXXNoexceptExprClass, Ty, VK_PRValue, OK_Ordinary), + Operand(Operand), Range(Keyword, RParen) { + CXXNoexceptExprBits.Value = Val == CT_Cannot; + setDependence(computeDependence(this, Val)); + } + + CXXNoexceptExpr(EmptyShell Empty) : Expr(CXXNoexceptExprClass, Empty) {} + + Expr *getOperand() const { return static_cast<Expr *>(Operand); } + + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } + SourceRange getSourceRange() const { return Range; } + + bool getValue() const { return CXXNoexceptExprBits.Value; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXNoexceptExprClass; + } + + // Iterators + child_range children() { return child_range(&Operand, &Operand + 1); } + + const_child_range children() const { + return const_child_range(&Operand, &Operand + 1); + } +}; + +/// Represents a C++11 pack expansion that produces a sequence of +/// expressions. +/// +/// A pack expansion expression contains a pattern (which itself is an +/// expression) followed by an ellipsis. For example: +/// +/// \code +/// template<typename F, typename ...Types> +/// void forward(F f, Types &&...args) { +/// f(static_cast<Types&&>(args)...); +/// } +/// \endcode +/// +/// Here, the argument to the function object \c f is a pack expansion whose +/// pattern is \c static_cast<Types&&>(args). When the \c forward function +/// template is instantiated, the pack expansion will instantiate to zero or +/// or more function arguments to the function object \c f. +class PackExpansionExpr : public Expr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + + SourceLocation EllipsisLoc; + + /// The number of expansions that will be produced by this pack + /// expansion expression, if known. + /// + /// When zero, the number of expansions is not known. Otherwise, this value + /// is the number of expansions + 1. + unsigned NumExpansions; + + Stmt *Pattern; + +public: + PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc, + std::optional<unsigned> NumExpansions) + : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), + Pattern->getObjectKind()), + EllipsisLoc(EllipsisLoc), + NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), + Pattern(Pattern) { + setDependence(computeDependence(this)); + } + + PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) {} + + /// Retrieve the pattern of the pack expansion. + Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); } + + /// Retrieve the pattern of the pack expansion. + const Expr *getPattern() const { return reinterpret_cast<Expr *>(Pattern); } + + /// Retrieve the location of the ellipsis that describes this pack + /// expansion. + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + + /// Determine the number of expansions that will be produced when + /// this pack expansion is instantiated, if already known. + std::optional<unsigned> getNumExpansions() const { + if (NumExpansions) + return NumExpansions - 1; + + return std::nullopt; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return Pattern->getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { return EllipsisLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == PackExpansionExprClass; + } + + // Iterators + child_range children() { + return child_range(&Pattern, &Pattern + 1); + } + + const_child_range children() const { + return const_child_range(&Pattern, &Pattern + 1); + } +}; + +/// Represents an expression that computes the length of a parameter +/// pack. +/// +/// \code +/// template<typename ...Types> +/// struct count { +/// static const unsigned value = sizeof...(Types); +/// }; +/// \endcode +class SizeOfPackExpr final + : public Expr, + private llvm::TrailingObjects<SizeOfPackExpr, TemplateArgument> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + + /// The location of the \c sizeof keyword. + SourceLocation OperatorLoc; + + /// The location of the name of the parameter pack. + SourceLocation PackLoc; + + /// The location of the closing parenthesis. + SourceLocation RParenLoc; + + /// The length of the parameter pack, if known. + /// + /// When this expression is not value-dependent, this is the length of + /// the pack. When the expression was parsed rather than instantiated + /// (and thus is value-dependent), this is zero. + /// + /// After partial substitution into a sizeof...(X) expression (for instance, + /// within an alias template or during function template argument deduction), + /// we store a trailing array of partially-substituted TemplateArguments, + /// and this is the length of that array. + unsigned Length; + + /// The parameter pack. + NamedDecl *Pack = nullptr; + + /// Create an expression that computes the length of + /// the given parameter pack. + SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, + SourceLocation PackLoc, SourceLocation RParenLoc, + std::optional<unsigned> Length, + ArrayRef<TemplateArgument> PartialArgs) + : Expr(SizeOfPackExprClass, SizeType, VK_PRValue, OK_Ordinary), + OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), + Length(Length ? *Length : PartialArgs.size()), Pack(Pack) { + assert((!Length || PartialArgs.empty()) && + "have partial args for non-dependent sizeof... expression"); + auto *Args = getTrailingObjects<TemplateArgument>(); + std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args); + setDependence(Length ? ExprDependence::None + : ExprDependence::ValueInstantiation); + } + + /// Create an empty expression. + SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs) + : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs) {} + +public: + static SizeOfPackExpr * + Create(ASTContext &Context, SourceLocation OperatorLoc, NamedDecl *Pack, + SourceLocation PackLoc, SourceLocation RParenLoc, + std::optional<unsigned> Length = std::nullopt, + ArrayRef<TemplateArgument> PartialArgs = std::nullopt); + static SizeOfPackExpr *CreateDeserialized(ASTContext &Context, + unsigned NumPartialArgs); + + /// Determine the location of the 'sizeof' keyword. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + + /// Determine the location of the parameter pack. + SourceLocation getPackLoc() const { return PackLoc; } + + /// Determine the location of the right parenthesis. + SourceLocation getRParenLoc() const { return RParenLoc; } + + /// Retrieve the parameter pack. + NamedDecl *getPack() const { return Pack; } + + /// Retrieve the length of the parameter pack. + /// + /// This routine may only be invoked when the expression is not + /// value-dependent. + unsigned getPackLength() const { + assert(!isValueDependent() && + "Cannot get the length of a value-dependent pack size expression"); + return Length; + } + + /// Determine whether this represents a partially-substituted sizeof... + /// expression, such as is produced for: + /// + /// template<typename ...Ts> using X = int[sizeof...(Ts)]; + /// template<typename ...Us> void f(X<Us..., 1, 2, 3, Us...>); + bool isPartiallySubstituted() const { + return isValueDependent() && Length; + } + + /// Get + ArrayRef<TemplateArgument> getPartialArguments() const { + assert(isPartiallySubstituted()); + const auto *Args = getTrailingObjects<TemplateArgument>(); + return llvm::ArrayRef(Args, Args + Length); + } + + SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SizeOfPackExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// Represents a reference to a non-type template parameter +/// that has been substituted with a template argument. +class SubstNonTypeTemplateParmExpr : public Expr { + friend class ASTReader; + friend class ASTStmtReader; + + /// The replacement expression. + Stmt *Replacement; + + /// The associated declaration and a flag indicating if it was a reference + /// parameter. For class NTTPs, we can't determine that based on the value + /// category alone. + llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndRef; + + unsigned Index : 15; + unsigned PackIndex : 16; + + explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) + : Expr(SubstNonTypeTemplateParmExprClass, Empty) {} + +public: + SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind, + SourceLocation Loc, Expr *Replacement, + Decl *AssociatedDecl, unsigned Index, + std::optional<unsigned> PackIndex, bool RefParam) + : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary), + Replacement(Replacement), + AssociatedDeclAndRef(AssociatedDecl, RefParam), Index(Index), + PackIndex(PackIndex ? *PackIndex + 1 : 0) { + assert(AssociatedDecl != nullptr); + SubstNonTypeTemplateParmExprBits.NameLoc = Loc; + setDependence(computeDependence(this)); + } + + SourceLocation getNameLoc() const { + return SubstNonTypeTemplateParmExprBits.NameLoc; + } + SourceLocation getBeginLoc() const { return getNameLoc(); } + SourceLocation getEndLoc() const { return getNameLoc(); } + + Expr *getReplacement() const { return cast<Expr>(Replacement); } + + /// A template-like entity which owns the whole pattern being substituted. + /// This will own a set of template parameters. + Decl *getAssociatedDecl() const { return AssociatedDeclAndRef.getPointer(); } + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getParameter()->getIndex()`. + unsigned getIndex() const { return Index; } + + std::optional<unsigned> getPackIndex() const { + if (PackIndex == 0) + return std::nullopt; + return PackIndex - 1; + } + + NonTypeTemplateParmDecl *getParameter() const; + + bool isReferenceParameter() const { return AssociatedDeclAndRef.getInt(); } + + /// Determine the substituted type of the template parameter. + QualType getParameterType(const ASTContext &Ctx) const; + + static bool classof(const Stmt *s) { + return s->getStmtClass() == SubstNonTypeTemplateParmExprClass; + } + + // Iterators + child_range children() { return child_range(&Replacement, &Replacement + 1); } + + const_child_range children() const { + return const_child_range(&Replacement, &Replacement + 1); + } +}; + +/// Represents a reference to a non-type template parameter pack that +/// has been substituted with a non-template argument pack. +/// +/// When a pack expansion in the source code contains multiple parameter packs +/// and those parameter packs correspond to different levels of template +/// parameter lists, this node is used to represent a non-type template +/// parameter pack from an outer level, which has already had its argument pack +/// substituted but that still lives within a pack expansion that itself +/// could not be instantiated. When actually performing a substitution into +/// that pack expansion (e.g., when all template parameters have corresponding +/// arguments), this type will be replaced with the appropriate underlying +/// expression at the current pack substitution index. +class SubstNonTypeTemplateParmPackExpr : public Expr { + friend class ASTReader; + friend class ASTStmtReader; + + /// The non-type template parameter pack itself. + Decl *AssociatedDecl; + + /// A pointer to the set of template arguments that this + /// parameter pack is instantiated with. + const TemplateArgument *Arguments; + + /// The number of template arguments in \c Arguments. + unsigned NumArguments : 16; + + unsigned Index : 16; + + /// The location of the non-type template parameter pack reference. + SourceLocation NameLoc; + + explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty) + : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {} + +public: + SubstNonTypeTemplateParmPackExpr(QualType T, ExprValueKind ValueKind, + SourceLocation NameLoc, + const TemplateArgument &ArgPack, + Decl *AssociatedDecl, unsigned Index); + + /// A template-like entity which owns the whole pattern being substituted. + /// This will own a set of template parameters. + Decl *getAssociatedDecl() const { return AssociatedDecl; } + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getParameterPack()->getIndex()`. + unsigned getIndex() const { return Index; } + + /// Retrieve the non-type template parameter pack being substituted. + NonTypeTemplateParmDecl *getParameterPack() const; + + /// Retrieve the location of the parameter pack name. + SourceLocation getParameterPackLocation() const { return NameLoc; } + + /// Retrieve the template argument pack containing the substituted + /// template arguments. + TemplateArgument getArgumentPack() const; + + SourceLocation getBeginLoc() const LLVM_READONLY { return NameLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return NameLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// Represents a reference to a function parameter pack or init-capture pack +/// that has been substituted but not yet expanded. +/// +/// When a pack expansion contains multiple parameter packs at different levels, +/// this node is used to represent a function parameter pack at an outer level +/// which we have already substituted to refer to expanded parameters, but where +/// the containing pack expansion cannot yet be expanded. +/// +/// \code +/// template<typename...Ts> struct S { +/// template<typename...Us> auto f(Ts ...ts) -> decltype(g(Us(ts)...)); +/// }; +/// template struct S<int, int>; +/// \endcode +class FunctionParmPackExpr final + : public Expr, + private llvm::TrailingObjects<FunctionParmPackExpr, VarDecl *> { + friend class ASTReader; + friend class ASTStmtReader; + friend TrailingObjects; + + /// The function parameter pack which was referenced. + VarDecl *ParamPack; + + /// The location of the function parameter pack reference. + SourceLocation NameLoc; + + /// The number of expansions of this pack. + unsigned NumParameters; + + FunctionParmPackExpr(QualType T, VarDecl *ParamPack, + SourceLocation NameLoc, unsigned NumParams, + VarDecl *const *Params); + +public: + static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T, + VarDecl *ParamPack, + SourceLocation NameLoc, + ArrayRef<VarDecl *> Params); + static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context, + unsigned NumParams); + + /// Get the parameter pack which this expression refers to. + VarDecl *getParameterPack() const { return ParamPack; } + + /// Get the location of the parameter pack. + SourceLocation getParameterPackLocation() const { return NameLoc; } + + /// Iterators over the parameters which the parameter pack expanded + /// into. + using iterator = VarDecl * const *; + iterator begin() const { return getTrailingObjects<VarDecl *>(); } + iterator end() const { return begin() + NumParameters; } + + /// Get the number of parameters in this parameter pack. + unsigned getNumExpansions() const { return NumParameters; } + + /// Get an expansion of the parameter pack by index. + VarDecl *getExpansion(unsigned I) const { return begin()[I]; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return NameLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return NameLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == FunctionParmPackExprClass; + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +/// Represents a prvalue temporary that is written into memory so that +/// a reference can bind to it. +/// +/// Prvalue expressions are materialized when they need to have an address +/// in memory for a reference to bind to. This happens when binding a +/// reference to the result of a conversion, e.g., +/// +/// \code +/// const int &r = 1.0; +/// \endcode +/// +/// Here, 1.0 is implicitly converted to an \c int. That resulting \c int is +/// then materialized via a \c MaterializeTemporaryExpr, and the reference +/// binds to the temporary. \c MaterializeTemporaryExprs are always glvalues +/// (either an lvalue or an xvalue, depending on the kind of reference binding +/// to it), maintaining the invariant that references always bind to glvalues. +/// +/// Reference binding and copy-elision can both extend the lifetime of a +/// temporary. When either happens, the expression will also track the +/// declaration which is responsible for the lifetime extension. +class MaterializeTemporaryExpr : public Expr { +private: + friend class ASTStmtReader; + friend class ASTStmtWriter; + + llvm::PointerUnion<Stmt *, LifetimeExtendedTemporaryDecl *> State; + +public: + MaterializeTemporaryExpr(QualType T, Expr *Temporary, + bool BoundToLvalueReference, + LifetimeExtendedTemporaryDecl *MTD = nullptr); + + MaterializeTemporaryExpr(EmptyShell Empty) + : Expr(MaterializeTemporaryExprClass, Empty) {} + + /// Retrieve the temporary-generating subexpression whose value will + /// be materialized into a glvalue. + Expr *getSubExpr() const { + return cast<Expr>( + State.is<Stmt *>() + ? State.get<Stmt *>() + : State.get<LifetimeExtendedTemporaryDecl *>()->getTemporaryExpr()); + } + + /// Retrieve the storage duration for the materialized temporary. + StorageDuration getStorageDuration() const { + return State.is<Stmt *>() ? SD_FullExpression + : State.get<LifetimeExtendedTemporaryDecl *>() + ->getStorageDuration(); + } + + /// Get the storage for the constant value of a materialized temporary + /// of static storage duration. + APValue *getOrCreateValue(bool MayCreate) const { + assert(State.is<LifetimeExtendedTemporaryDecl *>() && + "the temporary has not been lifetime extended"); + return State.get<LifetimeExtendedTemporaryDecl *>()->getOrCreateValue( + MayCreate); + } + + LifetimeExtendedTemporaryDecl *getLifetimeExtendedTemporaryDecl() { + return State.dyn_cast<LifetimeExtendedTemporaryDecl *>(); + } + const LifetimeExtendedTemporaryDecl * + getLifetimeExtendedTemporaryDecl() const { + return State.dyn_cast<LifetimeExtendedTemporaryDecl *>(); + } + + /// Get the declaration which triggered the lifetime-extension of this + /// temporary, if any. + ValueDecl *getExtendingDecl() { + return State.is<Stmt *>() ? nullptr + : State.get<LifetimeExtendedTemporaryDecl *>() + ->getExtendingDecl(); + } + const ValueDecl *getExtendingDecl() const { + return const_cast<MaterializeTemporaryExpr *>(this)->getExtendingDecl(); + } + + void setExtendingDecl(ValueDecl *ExtendedBy, unsigned ManglingNumber); + + unsigned getManglingNumber() const { + return State.is<Stmt *>() ? 0 + : State.get<LifetimeExtendedTemporaryDecl *>() + ->getManglingNumber(); + } + + /// Determine whether this materialized temporary is bound to an + /// lvalue reference; otherwise, it's bound to an rvalue reference. + bool isBoundToLvalueReference() const { return isLValue(); } + + /// Determine whether this temporary object is usable in constant + /// expressions, as specified in C++20 [expr.const]p4. + bool isUsableInConstantExpressions(const ASTContext &Context) const; + + SourceLocation getBeginLoc() const LLVM_READONLY { + return getSubExpr()->getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + return getSubExpr()->getEndLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == MaterializeTemporaryExprClass; + } + + // Iterators + child_range children() { + return State.is<Stmt *>() + ? child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1) + : State.get<LifetimeExtendedTemporaryDecl *>()->childrenExpr(); + } + + const_child_range children() const { + return State.is<Stmt *>() + ? const_child_range(State.getAddrOfPtr1(), + State.getAddrOfPtr1() + 1) + : const_cast<const LifetimeExtendedTemporaryDecl *>( + State.get<LifetimeExtendedTemporaryDecl *>()) + ->childrenExpr(); + } +}; + +/// Represents a folding of a pack over an operator. +/// +/// This expression is always dependent and represents a pack expansion of the +/// forms: +/// +/// ( expr op ... ) +/// ( ... op expr ) +/// ( expr op ... op expr ) +class CXXFoldExpr : public Expr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + + enum SubExpr { Callee, LHS, RHS, Count }; + + SourceLocation LParenLoc; + SourceLocation EllipsisLoc; + SourceLocation RParenLoc; + // When 0, the number of expansions is not known. Otherwise, this is one more + // than the number of expansions. + unsigned NumExpansions; + Stmt *SubExprs[SubExpr::Count]; + BinaryOperatorKind Opcode; + +public: + CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee, + SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Opcode, + SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc, + std::optional<unsigned> NumExpansions) + : Expr(CXXFoldExprClass, T, VK_PRValue, OK_Ordinary), + LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), + NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) { + SubExprs[SubExpr::Callee] = Callee; + SubExprs[SubExpr::LHS] = LHS; + SubExprs[SubExpr::RHS] = RHS; + setDependence(computeDependence(this)); + } + + CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {} + + UnresolvedLookupExpr *getCallee() const { + return static_cast<UnresolvedLookupExpr *>(SubExprs[SubExpr::Callee]); + } + Expr *getLHS() const { return static_cast<Expr*>(SubExprs[SubExpr::LHS]); } + Expr *getRHS() const { return static_cast<Expr*>(SubExprs[SubExpr::RHS]); } + + /// Does this produce a right-associated sequence of operators? + bool isRightFold() const { + return getLHS() && getLHS()->containsUnexpandedParameterPack(); + } + + /// Does this produce a left-associated sequence of operators? + bool isLeftFold() const { return !isRightFold(); } + + /// Get the pattern, that is, the operand that contains an unexpanded pack. + Expr *getPattern() const { return isLeftFold() ? getRHS() : getLHS(); } + + /// Get the operand that doesn't contain a pack, for a binary fold. + Expr *getInit() const { return isLeftFold() ? getLHS() : getRHS(); } + + SourceLocation getLParenLoc() const { return LParenLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + BinaryOperatorKind getOperator() const { return Opcode; } + + std::optional<unsigned> getNumExpansions() const { + if (NumExpansions) + return NumExpansions - 1; + return std::nullopt; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { + if (LParenLoc.isValid()) + return LParenLoc; + if (isLeftFold()) + return getEllipsisLoc(); + return getLHS()->getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + if (RParenLoc.isValid()) + return RParenLoc; + if (isRightFold()) + return getEllipsisLoc(); + return getRHS()->getEndLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXFoldExprClass; + } + + // Iterators + child_range children() { + return child_range(SubExprs, SubExprs + SubExpr::Count); + } + + const_child_range children() const { + return const_child_range(SubExprs, SubExprs + SubExpr::Count); + } +}; + +/// Represents a list-initialization with parenthesis. +/// +/// As per P0960R3, this is a C++20 feature that allows aggregate to +/// be initialized with a parenthesized list of values: +/// ``` +/// struct A { +/// int a; +/// double b; +/// }; +/// +/// void foo() { +/// A a1(0); // Well-formed in C++20 +/// A a2(1.5, 1.0); // Well-formed in C++20 +/// } +/// ``` +/// It has some sort of similiarity to braced +/// list-initialization, with some differences such as +/// it allows narrowing conversion whilst braced +/// list-initialization doesn't. +/// ``` +/// struct A { +/// char a; +/// }; +/// void foo() { +/// A a(1.5); // Well-formed in C++20 +/// A b{1.5}; // Ill-formed ! +/// } +/// ``` +class CXXParenListInitExpr final + : public Expr, + private llvm::TrailingObjects<CXXParenListInitExpr, Expr *> { + friend class TrailingObjects; + friend class ASTStmtReader; + friend class ASTStmtWriter; + + unsigned NumExprs; + unsigned NumUserSpecifiedExprs; + SourceLocation InitLoc, LParenLoc, RParenLoc; + llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit; + + CXXParenListInitExpr(ArrayRef<Expr *> Args, QualType T, + unsigned NumUserSpecifiedExprs, SourceLocation InitLoc, + SourceLocation LParenLoc, SourceLocation RParenLoc) + : Expr(CXXParenListInitExprClass, T, getValueKindForType(T), OK_Ordinary), + NumExprs(Args.size()), NumUserSpecifiedExprs(NumUserSpecifiedExprs), + InitLoc(InitLoc), LParenLoc(LParenLoc), RParenLoc(RParenLoc) { + std::copy(Args.begin(), Args.end(), getTrailingObjects<Expr *>()); + assert(NumExprs >= NumUserSpecifiedExprs && + "number of user specified inits is greater than the number of " + "passed inits"); + setDependence(computeDependence(this)); + } + + size_t numTrailingObjects(OverloadToken<Expr *>) const { return NumExprs; } + +public: + static CXXParenListInitExpr * + Create(ASTContext &C, ArrayRef<Expr *> Args, QualType T, + unsigned NumUserSpecifiedExprs, SourceLocation InitLoc, + SourceLocation LParenLoc, SourceLocation RParenLoc); + + static CXXParenListInitExpr *CreateEmpty(ASTContext &C, unsigned numExprs, + EmptyShell Empty); + + explicit CXXParenListInitExpr(EmptyShell Empty, unsigned NumExprs) + : Expr(CXXParenListInitExprClass, Empty), NumExprs(NumExprs), + NumUserSpecifiedExprs(0) {} + + void updateDependence() { setDependence(computeDependence(this)); } + + ArrayRef<Expr *> getInitExprs() { + return ArrayRef(getTrailingObjects<Expr *>(), NumExprs); + } + + const ArrayRef<Expr *> getInitExprs() const { + return ArrayRef(getTrailingObjects<Expr *>(), NumExprs); + } + + ArrayRef<Expr *> getUserSpecifiedInitExprs() { + return ArrayRef(getTrailingObjects<Expr *>(), NumUserSpecifiedExprs); + } + + const ArrayRef<Expr *> getUserSpecifiedInitExprs() const { + return ArrayRef(getTrailingObjects<Expr *>(), NumUserSpecifiedExprs); + } + + SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; } + + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + + SourceLocation getInitLoc() const LLVM_READONLY { return InitLoc; } + + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(getBeginLoc(), getEndLoc()); + } + + void setArrayFiller(Expr *E) { ArrayFillerOrUnionFieldInit = E; } + + Expr *getArrayFiller() { + return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>(); + } + + const Expr *getArrayFiller() const { + return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>(); + } + + void setInitializedFieldInUnion(FieldDecl *FD) { + ArrayFillerOrUnionFieldInit = FD; + } + + FieldDecl *getInitializedFieldInUnion() { + return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>(); + } + + const FieldDecl *getInitializedFieldInUnion() const { + return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>(); + } + + child_range children() { + Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); + return child_range(Begin, Begin + NumExprs); + } + + const_child_range children() const { + Stmt *const *Begin = + reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>()); + return const_child_range(Begin, Begin + NumExprs); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXParenListInitExprClass; + } +}; + +/// Represents an expression that might suspend coroutine execution; +/// either a co_await or co_yield expression. +/// +/// Evaluation of this expression first evaluates its 'ready' expression. If +/// that returns 'false': +/// -- execution of the coroutine is suspended +/// -- the 'suspend' expression is evaluated +/// -- if the 'suspend' expression returns 'false', the coroutine is +/// resumed +/// -- otherwise, control passes back to the resumer. +/// If the coroutine is not suspended, or when it is resumed, the 'resume' +/// expression is evaluated, and its result is the result of the overall +/// expression. +class CoroutineSuspendExpr : public Expr { + friend class ASTStmtReader; + + SourceLocation KeywordLoc; + + enum SubExpr { Operand, Common, Ready, Suspend, Resume, Count }; + + Stmt *SubExprs[SubExpr::Count]; + OpaqueValueExpr *OpaqueValue = nullptr; + +public: + CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Operand, + Expr *Common, Expr *Ready, Expr *Suspend, Expr *Resume, + OpaqueValueExpr *OpaqueValue) + : Expr(SC, Resume->getType(), Resume->getValueKind(), + Resume->getObjectKind()), + KeywordLoc(KeywordLoc), OpaqueValue(OpaqueValue) { + SubExprs[SubExpr::Operand] = Operand; + SubExprs[SubExpr::Common] = Common; + SubExprs[SubExpr::Ready] = Ready; + SubExprs[SubExpr::Suspend] = Suspend; + SubExprs[SubExpr::Resume] = Resume; + setDependence(computeDependence(this)); + } + + CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty, + Expr *Operand, Expr *Common) + : Expr(SC, Ty, VK_PRValue, OK_Ordinary), KeywordLoc(KeywordLoc) { + assert(Common->isTypeDependent() && Ty->isDependentType() && + "wrong constructor for non-dependent co_await/co_yield expression"); + SubExprs[SubExpr::Operand] = Operand; + SubExprs[SubExpr::Common] = Common; + SubExprs[SubExpr::Ready] = nullptr; + SubExprs[SubExpr::Suspend] = nullptr; + SubExprs[SubExpr::Resume] = nullptr; + setDependence(computeDependence(this)); + } + + CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { + SubExprs[SubExpr::Operand] = nullptr; + SubExprs[SubExpr::Common] = nullptr; + SubExprs[SubExpr::Ready] = nullptr; + SubExprs[SubExpr::Suspend] = nullptr; + SubExprs[SubExpr::Resume] = nullptr; + } + + Expr *getCommonExpr() const { + return static_cast<Expr*>(SubExprs[SubExpr::Common]); + } + + /// getOpaqueValue - Return the opaque value placeholder. + OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; } + + Expr *getReadyExpr() const { + return static_cast<Expr*>(SubExprs[SubExpr::Ready]); + } + + Expr *getSuspendExpr() const { + return static_cast<Expr*>(SubExprs[SubExpr::Suspend]); + } + + Expr *getResumeExpr() const { + return static_cast<Expr*>(SubExprs[SubExpr::Resume]); + } + + // The syntactic operand written in the code + Expr *getOperand() const { + return static_cast<Expr *>(SubExprs[SubExpr::Operand]); + } + + SourceLocation getKeywordLoc() const { return KeywordLoc; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; } + + SourceLocation getEndLoc() const LLVM_READONLY { + return getOperand()->getEndLoc(); + } + + child_range children() { + return child_range(SubExprs, SubExprs + SubExpr::Count); + } + + const_child_range children() const { + return const_child_range(SubExprs, SubExprs + SubExpr::Count); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoawaitExprClass || + T->getStmtClass() == CoyieldExprClass; + } +}; + +/// Represents a 'co_await' expression. +class CoawaitExpr : public CoroutineSuspendExpr { + friend class ASTStmtReader; + +public: + CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Common, + Expr *Ready, Expr *Suspend, Expr *Resume, + OpaqueValueExpr *OpaqueValue, bool IsImplicit = false) + : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Common, + Ready, Suspend, Resume, OpaqueValue) { + CoawaitBits.IsImplicit = IsImplicit; + } + + CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand, + Expr *Common, bool IsImplicit = false) + : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand, + Common) { + CoawaitBits.IsImplicit = IsImplicit; + } + + CoawaitExpr(EmptyShell Empty) + : CoroutineSuspendExpr(CoawaitExprClass, Empty) {} + + bool isImplicit() const { return CoawaitBits.IsImplicit; } + void setIsImplicit(bool value = true) { CoawaitBits.IsImplicit = value; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoawaitExprClass; + } +}; + +/// Represents a 'co_await' expression while the type of the promise +/// is dependent. +class DependentCoawaitExpr : public Expr { + friend class ASTStmtReader; + + SourceLocation KeywordLoc; + Stmt *SubExprs[2]; + +public: + DependentCoawaitExpr(SourceLocation KeywordLoc, QualType Ty, Expr *Op, + UnresolvedLookupExpr *OpCoawait) + : Expr(DependentCoawaitExprClass, Ty, VK_PRValue, OK_Ordinary), + KeywordLoc(KeywordLoc) { + // NOTE: A co_await expression is dependent on the coroutines promise + // type and may be dependent even when the `Op` expression is not. + assert(Ty->isDependentType() && + "wrong constructor for non-dependent co_await/co_yield expression"); + SubExprs[0] = Op; + SubExprs[1] = OpCoawait; + setDependence(computeDependence(this)); + } + + DependentCoawaitExpr(EmptyShell Empty) + : Expr(DependentCoawaitExprClass, Empty) {} + + Expr *getOperand() const { return cast<Expr>(SubExprs[0]); } + + UnresolvedLookupExpr *getOperatorCoawaitLookup() const { + return cast<UnresolvedLookupExpr>(SubExprs[1]); + } + + SourceLocation getKeywordLoc() const { return KeywordLoc; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; } + + SourceLocation getEndLoc() const LLVM_READONLY { + return getOperand()->getEndLoc(); + } + + child_range children() { return child_range(SubExprs, SubExprs + 2); } + + const_child_range children() const { + return const_child_range(SubExprs, SubExprs + 2); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DependentCoawaitExprClass; + } +}; + +/// Represents a 'co_yield' expression. +class CoyieldExpr : public CoroutineSuspendExpr { + friend class ASTStmtReader; + +public: + CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Common, + Expr *Ready, Expr *Suspend, Expr *Resume, + OpaqueValueExpr *OpaqueValue) + : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Common, + Ready, Suspend, Resume, OpaqueValue) {} + CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand, + Expr *Common) + : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand, + Common) {} + CoyieldExpr(EmptyShell Empty) + : CoroutineSuspendExpr(CoyieldExprClass, Empty) {} + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoyieldExprClass; + } +}; + +/// Represents a C++2a __builtin_bit_cast(T, v) expression. Used to implement +/// std::bit_cast. These can sometimes be evaluated as part of a constant +/// expression, but otherwise CodeGen to a simple memcpy in general. +class BuiltinBitCastExpr final + : public ExplicitCastExpr, + private llvm::TrailingObjects<BuiltinBitCastExpr, CXXBaseSpecifier *> { + friend class ASTStmtReader; + friend class CastExpr; + friend TrailingObjects; + + SourceLocation KWLoc; + SourceLocation RParenLoc; + +public: + BuiltinBitCastExpr(QualType T, ExprValueKind VK, CastKind CK, Expr *SrcExpr, + TypeSourceInfo *DstType, SourceLocation KWLoc, + SourceLocation RParenLoc) + : ExplicitCastExpr(BuiltinBitCastExprClass, T, VK, CK, SrcExpr, 0, false, + DstType), + KWLoc(KWLoc), RParenLoc(RParenLoc) {} + BuiltinBitCastExpr(EmptyShell Empty) + : ExplicitCastExpr(BuiltinBitCastExprClass, Empty, 0, false) {} + + SourceLocation getBeginLoc() const LLVM_READONLY { return KWLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == BuiltinBitCastExprClass; + } +}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_EXPRCXX_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif |