summaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ExprCXX.cpp')
-rw-r--r--clang/lib/AST/ExprCXX.cpp1831
1 files changed, 1831 insertions, 0 deletions
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
new file mode 100644
index 000000000000..904928bdf286
--- /dev/null
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -0,0 +1,1831 @@
+//===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the subclesses of Expr class declared in ExprCXX.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/LambdaCapture.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <memory>
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Child Iterators for iterating over subexpressions/substatements
+//===----------------------------------------------------------------------===//
+
+bool CXXOperatorCallExpr::isInfixBinaryOp() const {
+ // An infix binary operator is any operator with two arguments other than
+ // operator() and operator[]. Note that none of these operators can have
+ // default arguments, so it suffices to check the number of argument
+ // expressions.
+ if (getNumArgs() != 2)
+ return false;
+
+ switch (getOperator()) {
+ case OO_Call: case OO_Subscript:
+ return false;
+ default:
+ return true;
+ }
+}
+
+CXXRewrittenBinaryOperator::DecomposedForm
+CXXRewrittenBinaryOperator::getDecomposedForm() const {
+ DecomposedForm Result = {};
+ const Expr *E = getSemanticForm()->IgnoreImplicit();
+
+ // Remove an outer '!' if it exists (only happens for a '!=' rewrite).
+ bool SkippedNot = false;
+ if (auto *NotEq = dyn_cast<UnaryOperator>(E)) {
+ assert(NotEq->getOpcode() == UO_LNot);
+ E = NotEq->getSubExpr()->IgnoreImplicit();
+ SkippedNot = true;
+ }
+
+ // Decompose the outer binary operator.
+ if (auto *BO = dyn_cast<BinaryOperator>(E)) {
+ assert(!SkippedNot || BO->getOpcode() == BO_EQ);
+ Result.Opcode = SkippedNot ? BO_NE : BO->getOpcode();
+ Result.LHS = BO->getLHS();
+ Result.RHS = BO->getRHS();
+ Result.InnerBinOp = BO;
+ } else if (auto *BO = dyn_cast<CXXOperatorCallExpr>(E)) {
+ assert(!SkippedNot || BO->getOperator() == OO_EqualEqual);
+ assert(BO->isInfixBinaryOp());
+ switch (BO->getOperator()) {
+ case OO_Less: Result.Opcode = BO_LT; break;
+ case OO_LessEqual: Result.Opcode = BO_LE; break;
+ case OO_Greater: Result.Opcode = BO_GT; break;
+ case OO_GreaterEqual: Result.Opcode = BO_GE; break;
+ case OO_Spaceship: Result.Opcode = BO_Cmp; break;
+ case OO_EqualEqual: Result.Opcode = SkippedNot ? BO_NE : BO_EQ; break;
+ default: llvm_unreachable("unexpected binop in rewritten operator expr");
+ }
+ Result.LHS = BO->getArg(0);
+ Result.RHS = BO->getArg(1);
+ Result.InnerBinOp = BO;
+ } else {
+ llvm_unreachable("unexpected rewritten operator form");
+ }
+
+ // Put the operands in the right order for == and !=, and canonicalize the
+ // <=> subexpression onto the LHS for all other forms.
+ if (isReversed())
+ std::swap(Result.LHS, Result.RHS);
+
+ // If this isn't a spaceship rewrite, we're done.
+ if (Result.Opcode == BO_EQ || Result.Opcode == BO_NE)
+ return Result;
+
+ // Otherwise, we expect a <=> to now be on the LHS.
+ E = Result.LHS->IgnoreImplicit();
+ if (auto *BO = dyn_cast<BinaryOperator>(E)) {
+ assert(BO->getOpcode() == BO_Cmp);
+ Result.LHS = BO->getLHS();
+ Result.RHS = BO->getRHS();
+ Result.InnerBinOp = BO;
+ } else if (auto *BO = dyn_cast<CXXOperatorCallExpr>(E)) {
+ assert(BO->getOperator() == OO_Spaceship);
+ Result.LHS = BO->getArg(0);
+ Result.RHS = BO->getArg(1);
+ Result.InnerBinOp = BO;
+ } else {
+ llvm_unreachable("unexpected rewritten operator form");
+ }
+
+ // Put the comparison operands in the right order.
+ if (isReversed())
+ std::swap(Result.LHS, Result.RHS);
+ return Result;
+}
+
+bool CXXTypeidExpr::isPotentiallyEvaluated() const {
+ if (isTypeOperand())
+ return false;
+
+ // C++11 [expr.typeid]p3:
+ // When typeid is applied to an expression other than a glvalue of
+ // polymorphic class type, [...] the expression is an unevaluated operand.
+ const Expr *E = getExprOperand();
+ if (const CXXRecordDecl *RD = E->getType()->getAsCXXRecordDecl())
+ if (RD->isPolymorphic() && E->isGLValue())
+ return true;
+
+ return false;
+}
+
+QualType CXXTypeidExpr::getTypeOperand(ASTContext &Context) const {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
+ Qualifiers Quals;
+ return Context.getUnqualifiedArrayType(
+ Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType(), Quals);
+}
+
+QualType CXXUuidofExpr::getTypeOperand(ASTContext &Context) const {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
+ Qualifiers Quals;
+ return Context.getUnqualifiedArrayType(
+ Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType(), Quals);
+}
+
+// CXXScalarValueInitExpr
+SourceLocation CXXScalarValueInitExpr::getBeginLoc() const {
+ return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : getRParenLoc();
+}
+
+// CXXNewExpr
+CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
+ FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
+ bool UsualArrayDeleteWantsSize,
+ ArrayRef<Expr *> PlacementArgs, SourceRange TypeIdParens,
+ Optional<Expr *> ArraySize,
+ InitializationStyle InitializationStyle,
+ Expr *Initializer, QualType Ty,
+ TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
+ SourceRange DirectInitRange)
+ : Expr(CXXNewExprClass, Ty, VK_RValue, OK_Ordinary, Ty->isDependentType(),
+ Ty->isDependentType(), Ty->isInstantiationDependentType(),
+ Ty->containsUnexpandedParameterPack()),
+ OperatorNew(OperatorNew), OperatorDelete(OperatorDelete),
+ AllocatedTypeInfo(AllocatedTypeInfo), Range(Range),
+ DirectInitRange(DirectInitRange) {
+
+ assert((Initializer != nullptr || InitializationStyle == NoInit) &&
+ "Only NoInit can have no initializer!");
+
+ CXXNewExprBits.IsGlobalNew = IsGlobalNew;
+ CXXNewExprBits.IsArray = ArraySize.hasValue();
+ CXXNewExprBits.ShouldPassAlignment = ShouldPassAlignment;
+ CXXNewExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize;
+ CXXNewExprBits.StoredInitializationStyle =
+ Initializer ? InitializationStyle + 1 : 0;
+ bool IsParenTypeId = TypeIdParens.isValid();
+ CXXNewExprBits.IsParenTypeId = IsParenTypeId;
+ CXXNewExprBits.NumPlacementArgs = PlacementArgs.size();
+
+ if (ArraySize) {
+ if (Expr *SizeExpr = *ArraySize) {
+ if (SizeExpr->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (SizeExpr->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (SizeExpr->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+ }
+
+ getTrailingObjects<Stmt *>()[arraySizeOffset()] = *ArraySize;
+ }
+
+ if (Initializer) {
+ if (Initializer->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (Initializer->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (Initializer->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ getTrailingObjects<Stmt *>()[initExprOffset()] = Initializer;
+ }
+
+ for (unsigned I = 0; I != PlacementArgs.size(); ++I) {
+ if (PlacementArgs[I]->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (PlacementArgs[I]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (PlacementArgs[I]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ getTrailingObjects<Stmt *>()[placementNewArgsOffset() + I] =
+ PlacementArgs[I];
+ }
+
+ if (IsParenTypeId)
+ getTrailingObjects<SourceRange>()[0] = TypeIdParens;
+
+ switch (getInitializationStyle()) {
+ case CallInit:
+ this->Range.setEnd(DirectInitRange.getEnd());
+ break;
+ case ListInit:
+ this->Range.setEnd(getInitializer()->getSourceRange().getEnd());
+ break;
+ default:
+ if (IsParenTypeId)
+ this->Range.setEnd(TypeIdParens.getEnd());
+ break;
+ }
+}
+
+CXXNewExpr::CXXNewExpr(EmptyShell Empty, bool IsArray,
+ unsigned NumPlacementArgs, bool IsParenTypeId)
+ : Expr(CXXNewExprClass, Empty) {
+ CXXNewExprBits.IsArray = IsArray;
+ CXXNewExprBits.NumPlacementArgs = NumPlacementArgs;
+ CXXNewExprBits.IsParenTypeId = IsParenTypeId;
+}
+
+CXXNewExpr *
+CXXNewExpr::Create(const ASTContext &Ctx, bool IsGlobalNew,
+ FunctionDecl *OperatorNew, FunctionDecl *OperatorDelete,
+ bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize,
+ ArrayRef<Expr *> PlacementArgs, SourceRange TypeIdParens,
+ Optional<Expr *> ArraySize,
+ InitializationStyle InitializationStyle, Expr *Initializer,
+ QualType Ty, TypeSourceInfo *AllocatedTypeInfo,
+ SourceRange Range, SourceRange DirectInitRange) {
+ bool IsArray = ArraySize.hasValue();
+ bool HasInit = Initializer != nullptr;
+ unsigned NumPlacementArgs = PlacementArgs.size();
+ bool IsParenTypeId = TypeIdParens.isValid();
+ void *Mem =
+ Ctx.Allocate(totalSizeToAlloc<Stmt *, SourceRange>(
+ IsArray + HasInit + NumPlacementArgs, IsParenTypeId),
+ alignof(CXXNewExpr));
+ return new (Mem)
+ CXXNewExpr(IsGlobalNew, OperatorNew, OperatorDelete, ShouldPassAlignment,
+ UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens,
+ ArraySize, InitializationStyle, Initializer, Ty,
+ AllocatedTypeInfo, Range, DirectInitRange);
+}
+
+CXXNewExpr *CXXNewExpr::CreateEmpty(const ASTContext &Ctx, bool IsArray,
+ bool HasInit, unsigned NumPlacementArgs,
+ bool IsParenTypeId) {
+ void *Mem =
+ Ctx.Allocate(totalSizeToAlloc<Stmt *, SourceRange>(
+ IsArray + HasInit + NumPlacementArgs, IsParenTypeId),
+ alignof(CXXNewExpr));
+ return new (Mem)
+ CXXNewExpr(EmptyShell(), IsArray, NumPlacementArgs, IsParenTypeId);
+}
+
+bool CXXNewExpr::shouldNullCheckAllocation() const {
+ return getOperatorNew()
+ ->getType()
+ ->castAs<FunctionProtoType>()
+ ->isNothrow() &&
+ !getOperatorNew()->isReservedGlobalPlacementOperator();
+}
+
+// CXXDeleteExpr
+QualType CXXDeleteExpr::getDestroyedType() const {
+ const Expr *Arg = getArgument();
+
+ // For a destroying operator delete, we may have implicitly converted the
+ // pointer type to the type of the parameter of the 'operator delete'
+ // function.
+ while (const auto *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
+ if (ICE->getCastKind() == CK_DerivedToBase ||
+ ICE->getCastKind() == CK_UncheckedDerivedToBase ||
+ ICE->getCastKind() == CK_NoOp) {
+ assert((ICE->getCastKind() == CK_NoOp ||
+ getOperatorDelete()->isDestroyingOperatorDelete()) &&
+ "only a destroying operator delete can have a converted arg");
+ Arg = ICE->getSubExpr();
+ } else
+ break;
+ }
+
+ // The type-to-delete may not be a pointer if it's a dependent type.
+ const QualType ArgType = Arg->getType();
+
+ if (ArgType->isDependentType() && !ArgType->isPointerType())
+ return QualType();
+
+ return ArgType->castAs<PointerType>()->getPointeeType();
+}
+
+// CXXPseudoDestructorExpr
+PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info)
+ : Type(Info) {
+ Location = Info->getTypeLoc().getLocalSourceRange().getBegin();
+}
+
+CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context,
+ Expr *Base, bool isArrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType,
+ SourceLocation ColonColonLoc, SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage DestroyedType)
+ : Expr(CXXPseudoDestructorExprClass,
+ Context.BoundMemberTy,
+ VK_RValue, OK_Ordinary,
+ /*isTypeDependent=*/(Base->isTypeDependent() ||
+ (DestroyedType.getTypeSourceInfo() &&
+ DestroyedType.getTypeSourceInfo()->getType()->isDependentType())),
+ /*isValueDependent=*/Base->isValueDependent(),
+ (Base->isInstantiationDependent() ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) ||
+ (ScopeType &&
+ ScopeType->getType()->isInstantiationDependentType()) ||
+ (DestroyedType.getTypeSourceInfo() &&
+ DestroyedType.getTypeSourceInfo()->getType()
+ ->isInstantiationDependentType())),
+ // ContainsUnexpandedParameterPack
+ (Base->containsUnexpandedParameterPack() ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()) ||
+ (ScopeType &&
+ ScopeType->getType()->containsUnexpandedParameterPack()) ||
+ (DestroyedType.getTypeSourceInfo() &&
+ DestroyedType.getTypeSourceInfo()->getType()
+ ->containsUnexpandedParameterPack()))),
+ Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
+ OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
+ ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc),
+ DestroyedType(DestroyedType) {}
+
+QualType CXXPseudoDestructorExpr::getDestroyedType() const {
+ if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
+ return TInfo->getType();
+
+ return QualType();
+}
+
+SourceLocation CXXPseudoDestructorExpr::getEndLoc() const {
+ SourceLocation End = DestroyedType.getLocation();
+ if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
+ End = TInfo->getTypeLoc().getLocalSourceRange().getEnd();
+ return End;
+}
+
+// UnresolvedLookupExpr
+UnresolvedLookupExpr::UnresolvedLookupExpr(
+ const ASTContext &Context, CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded,
+ const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End)
+ : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc,
+ TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, false,
+ false, false),
+ NamingClass(NamingClass) {
+ UnresolvedLookupExprBits.RequiresADL = RequiresADL;
+ UnresolvedLookupExprBits.Overloaded = Overloaded;
+}
+
+UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty,
+ unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo)
+ : OverloadExpr(UnresolvedLookupExprClass, Empty, NumResults,
+ HasTemplateKWAndArgsInfo) {}
+
+UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
+ const ASTContext &Context, CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
+ bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
+ unsigned NumResults = End - Begin;
+ unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(NumResults, 0, 0);
+ void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
+ return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc,
+ SourceLocation(), NameInfo, RequiresADL,
+ Overloaded, nullptr, Begin, End);
+}
+
+UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
+ const ASTContext &Context, CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo, bool RequiresADL,
+ const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
+ assert(Args || TemplateKWLoc.isValid());
+ unsigned NumResults = End - Begin;
+ unsigned NumTemplateArgs = Args ? Args->size() : 0;
+ unsigned Size =
+ totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(NumResults, 1, NumTemplateArgs);
+ void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
+ return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc,
+ TemplateKWLoc, NameInfo, RequiresADL,
+ /*Overloaded*/ true, Args, Begin, End);
+}
+
+UnresolvedLookupExpr *UnresolvedLookupExpr::CreateEmpty(
+ const ASTContext &Context, unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) {
+ assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
+ unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(
+ NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
+ return new (Mem)
+ UnresolvedLookupExpr(EmptyShell(), NumResults, HasTemplateKWAndArgsInfo);
+}
+
+OverloadExpr::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)
+ : Expr(
+ SC, Context.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent,
+ KnownDependent,
+ (KnownInstantiationDependent || NameInfo.isInstantiationDependent() ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
+ (KnownContainsUnexpandedParameterPack ||
+ NameInfo.containsUnexpandedParameterPack() ||
+ (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()))),
+ NameInfo(NameInfo), QualifierLoc(QualifierLoc) {
+ unsigned NumResults = End - Begin;
+ OverloadExprBits.NumResults = NumResults;
+ OverloadExprBits.HasTemplateKWAndArgsInfo =
+ (TemplateArgs != nullptr ) || TemplateKWLoc.isValid();
+
+ if (NumResults) {
+ // Determine whether this expression is type-dependent.
+ for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I) {
+ if ((*I)->getDeclContext()->isDependentContext() ||
+ isa<UnresolvedUsingValueDecl>(*I)) {
+ ExprBits.TypeDependent = true;
+ ExprBits.ValueDependent = true;
+ ExprBits.InstantiationDependent = true;
+ }
+ }
+
+ // Copy the results to the trailing array past UnresolvedLookupExpr
+ // or UnresolvedMemberExpr.
+ DeclAccessPair *Results = getTrailingResults();
+ memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
+ }
+
+ // If we have explicit template arguments, check for dependent
+ // template arguments and whether they contain any unexpanded pack
+ // expansions.
+ if (TemplateArgs) {
+ bool Dependent = false;
+ bool InstantiationDependent = false;
+ bool ContainsUnexpandedParameterPack = false;
+ getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(
+ TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc(),
+ Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
+
+ if (Dependent) {
+ ExprBits.TypeDependent = true;
+ ExprBits.ValueDependent = true;
+ }
+ if (InstantiationDependent)
+ ExprBits.InstantiationDependent = true;
+ if (ContainsUnexpandedParameterPack)
+ ExprBits.ContainsUnexpandedParameterPack = true;
+ } else if (TemplateKWLoc.isValid()) {
+ getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
+ }
+
+ if (isTypeDependent())
+ setType(Context.DependentTy);
+}
+
+OverloadExpr::OverloadExpr(StmtClass SC, EmptyShell Empty, unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo)
+ : Expr(SC, Empty) {
+ OverloadExprBits.NumResults = NumResults;
+ OverloadExprBits.HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
+}
+
+// DependentScopeDeclRefExpr
+DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(
+ QualType Ty, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *Args)
+ : Expr(
+ DependentScopeDeclRefExprClass, Ty, VK_LValue, OK_Ordinary, true,
+ true,
+ (NameInfo.isInstantiationDependent() ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
+ (NameInfo.containsUnexpandedParameterPack() ||
+ (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()))),
+ QualifierLoc(QualifierLoc), NameInfo(NameInfo) {
+ DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
+ (Args != nullptr) || TemplateKWLoc.isValid();
+ if (Args) {
+ bool Dependent = true;
+ bool InstantiationDependent = true;
+ bool ContainsUnexpandedParameterPack
+ = ExprBits.ContainsUnexpandedParameterPack;
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>(),
+ Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
+ ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+ } else if (TemplateKWLoc.isValid()) {
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc);
+ }
+}
+
+DependentScopeDeclRefExpr *DependentScopeDeclRefExpr::Create(
+ const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *Args) {
+ assert(QualifierLoc && "should be created for dependent qualifiers");
+ bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid();
+ std::size_t Size =
+ totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasTemplateKWAndArgsInfo, Args ? Args->size() : 0);
+ void *Mem = Context.Allocate(Size);
+ return new (Mem) DependentScopeDeclRefExpr(Context.DependentTy, QualifierLoc,
+ TemplateKWLoc, NameInfo, Args);
+}
+
+DependentScopeDeclRefExpr *
+DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &Context,
+ bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs) {
+ assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
+ std::size_t Size =
+ totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ void *Mem = Context.Allocate(Size);
+ auto *E = new (Mem) DependentScopeDeclRefExpr(
+ QualType(), NestedNameSpecifierLoc(), SourceLocation(),
+ DeclarationNameInfo(), nullptr);
+ E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
+ HasTemplateKWAndArgsInfo;
+ return E;
+}
+
+SourceLocation CXXConstructExpr::getBeginLoc() const {
+ if (isa<CXXTemporaryObjectExpr>(this))
+ return cast<CXXTemporaryObjectExpr>(this)->getBeginLoc();
+ return getLocation();
+}
+
+SourceLocation CXXConstructExpr::getEndLoc() const {
+ if (isa<CXXTemporaryObjectExpr>(this))
+ return cast<CXXTemporaryObjectExpr>(this)->getEndLoc();
+
+ if (ParenOrBraceRange.isValid())
+ return ParenOrBraceRange.getEnd();
+
+ SourceLocation End = getLocation();
+ for (unsigned I = getNumArgs(); I > 0; --I) {
+ const Expr *Arg = getArg(I-1);
+ if (!Arg->isDefaultArgument()) {
+ SourceLocation NewEnd = Arg->getEndLoc();
+ if (NewEnd.isValid()) {
+ End = NewEnd;
+ break;
+ }
+ }
+ }
+
+ return End;
+}
+
+CXXOperatorCallExpr::CXXOperatorCallExpr(OverloadedOperatorKind OpKind,
+ Expr *Fn, ArrayRef<Expr *> Args,
+ QualType Ty, ExprValueKind VK,
+ SourceLocation OperatorLoc,
+ FPOptions FPFeatures,
+ ADLCallKind UsesADL)
+ : CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
+ OperatorLoc, /*MinNumArgs=*/0, UsesADL) {
+ CXXOperatorCallExprBits.OperatorKind = OpKind;
+ CXXOperatorCallExprBits.FPFeatures = FPFeatures.getInt();
+ assert(
+ (CXXOperatorCallExprBits.OperatorKind == static_cast<unsigned>(OpKind)) &&
+ "OperatorKind overflow!");
+ assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getInt()) &&
+ "FPFeatures overflow!");
+ Range = getSourceRangeImpl();
+}
+
+CXXOperatorCallExpr::CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
+
+CXXOperatorCallExpr *CXXOperatorCallExpr::Create(
+ const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+ SourceLocation OperatorLoc, FPOptions FPFeatures, ADLCallKind UsesADL) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned NumArgs = Args.size();
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects,
+ alignof(CXXOperatorCallExpr));
+ return new (Mem) CXXOperatorCallExpr(OpKind, Fn, Args, Ty, VK, OperatorLoc,
+ FPFeatures, UsesADL);
+}
+
+CXXOperatorCallExpr *CXXOperatorCallExpr::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs,
+ EmptyShell Empty) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects,
+ alignof(CXXOperatorCallExpr));
+ return new (Mem) CXXOperatorCallExpr(NumArgs, Empty);
+}
+
+SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const {
+ OverloadedOperatorKind Kind = getOperator();
+ if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
+ if (getNumArgs() == 1)
+ // Prefix operator
+ return SourceRange(getOperatorLoc(), getArg(0)->getEndLoc());
+ else
+ // Postfix operator
+ return SourceRange(getArg(0)->getBeginLoc(), getOperatorLoc());
+ } else if (Kind == OO_Arrow) {
+ return getArg(0)->getSourceRange();
+ } else if (Kind == OO_Call) {
+ return SourceRange(getArg(0)->getBeginLoc(), getRParenLoc());
+ } else if (Kind == OO_Subscript) {
+ return SourceRange(getArg(0)->getBeginLoc(), getRParenLoc());
+ } else if (getNumArgs() == 1) {
+ return SourceRange(getOperatorLoc(), getArg(0)->getEndLoc());
+ } else if (getNumArgs() == 2) {
+ return SourceRange(getArg(0)->getBeginLoc(), getArg(1)->getEndLoc());
+ } else {
+ return getOperatorLoc();
+ }
+}
+
+CXXMemberCallExpr::CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args,
+ QualType Ty, ExprValueKind VK,
+ SourceLocation RP, unsigned MinNumArgs)
+ : CallExpr(CXXMemberCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, RP,
+ MinNumArgs, NotADL) {}
+
+CXXMemberCallExpr::CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
+
+CXXMemberCallExpr *CXXMemberCallExpr::Create(const ASTContext &Ctx, Expr *Fn,
+ ArrayRef<Expr *> Args, QualType Ty,
+ ExprValueKind VK,
+ SourceLocation RP,
+ unsigned MinNumArgs) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects,
+ alignof(CXXMemberCallExpr));
+ return new (Mem) CXXMemberCallExpr(Fn, Args, Ty, VK, RP, MinNumArgs);
+}
+
+CXXMemberCallExpr *CXXMemberCallExpr::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs,
+ EmptyShell Empty) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects,
+ alignof(CXXMemberCallExpr));
+ return new (Mem) CXXMemberCallExpr(NumArgs, Empty);
+}
+
+Expr *CXXMemberCallExpr::getImplicitObjectArgument() const {
+ const Expr *Callee = getCallee()->IgnoreParens();
+ if (const auto *MemExpr = dyn_cast<MemberExpr>(Callee))
+ return MemExpr->getBase();
+ if (const auto *BO = dyn_cast<BinaryOperator>(Callee))
+ if (BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI)
+ return BO->getLHS();
+
+ // FIXME: Will eventually need to cope with member pointers.
+ return nullptr;
+}
+
+QualType CXXMemberCallExpr::getObjectType() const {
+ QualType Ty = getImplicitObjectArgument()->getType();
+ if (Ty->isPointerType())
+ Ty = Ty->getPointeeType();
+ return Ty;
+}
+
+CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const {
+ if (const auto *MemExpr = dyn_cast<MemberExpr>(getCallee()->IgnoreParens()))
+ return cast<CXXMethodDecl>(MemExpr->getMemberDecl());
+
+ // FIXME: Will eventually need to cope with member pointers.
+ return nullptr;
+}
+
+CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() const {
+ Expr* ThisArg = getImplicitObjectArgument();
+ if (!ThisArg)
+ return nullptr;
+
+ if (ThisArg->getType()->isAnyPointerType())
+ return ThisArg->getType()->getPointeeType()->getAsCXXRecordDecl();
+
+ return ThisArg->getType()->getAsCXXRecordDecl();
+}
+
+//===----------------------------------------------------------------------===//
+// Named casts
+//===----------------------------------------------------------------------===//
+
+/// getCastName - Get the name of the C++ cast being used, e.g.,
+/// "static_cast", "dynamic_cast", "reinterpret_cast", or
+/// "const_cast". The returned pointer must not be freed.
+const char *CXXNamedCastExpr::getCastName() const {
+ switch (getStmtClass()) {
+ case CXXStaticCastExprClass: return "static_cast";
+ case CXXDynamicCastExprClass: return "dynamic_cast";
+ case CXXReinterpretCastExprClass: return "reinterpret_cast";
+ case CXXConstCastExprClass: return "const_cast";
+ default: return "<invalid cast>";
+ }
+}
+
+CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T,
+ ExprValueKind VK,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L,
+ SourceLocation RParenLoc,
+ SourceRange AngleBrackets) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ auto *E =
+ new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
+ RParenLoc, AngleBrackets);
+ if (PathSize)
+ std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+ E->getTrailingObjects<CXXBaseSpecifier *>());
+ return E;
+}
+
+CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(const ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T,
+ ExprValueKind VK,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L,
+ SourceLocation RParenLoc,
+ SourceRange AngleBrackets) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ auto *E =
+ new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
+ RParenLoc, AngleBrackets);
+ if (PathSize)
+ std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+ E->getTrailingObjects<CXXBaseSpecifier *>());
+ return E;
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(const ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
+}
+
+/// isAlwaysNull - Return whether the result of the dynamic_cast is proven
+/// to always be null. For example:
+///
+/// struct A { };
+/// struct B final : A { };
+/// struct C { };
+///
+/// C *f(B* b) { return dynamic_cast<C*>(b); }
+bool CXXDynamicCastExpr::isAlwaysNull() const
+{
+ QualType SrcType = getSubExpr()->getType();
+ QualType DestType = getType();
+
+ if (const auto *SrcPTy = SrcType->getAs<PointerType>()) {
+ SrcType = SrcPTy->getPointeeType();
+ DestType = DestType->castAs<PointerType>()->getPointeeType();
+ }
+
+ if (DestType->isVoidType())
+ return false;
+
+ const auto *SrcRD =
+ cast<CXXRecordDecl>(SrcType->castAs<RecordType>()->getDecl());
+
+ if (!SrcRD->hasAttr<FinalAttr>())
+ return false;
+
+ const auto *DestRD =
+ cast<CXXRecordDecl>(DestType->castAs<RecordType>()->getDecl());
+
+ return !DestRD->isDerivedFrom(SrcRD);
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T,
+ ExprValueKind VK, CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation RParenLoc,
+ SourceRange AngleBrackets) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ auto *E =
+ new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
+ RParenLoc, AngleBrackets);
+ if (PathSize)
+ std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+ E->getTrailingObjects<CXXBaseSpecifier *>());
+ return E;
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::Create(const ASTContext &C, QualType T,
+ ExprValueKind VK, Expr *Op,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L,
+ SourceLocation RParenLoc,
+ SourceRange AngleBrackets) {
+ return new (C) CXXConstCastExpr(T, VK, Op, WrittenTy, L, RParenLoc, AngleBrackets);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(const ASTContext &C) {
+ return new (C) CXXConstCastExpr(EmptyShell());
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
+ TypeSourceInfo *Written, CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ SourceLocation L, SourceLocation R) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ auto *E =
+ new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R);
+ if (PathSize)
+ std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+ E->getTrailingObjects<CXXBaseSpecifier *>());
+ return E;
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
+ return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
+}
+
+SourceLocation CXXFunctionalCastExpr::getBeginLoc() const {
+ return getTypeInfoAsWritten()->getTypeLoc().getBeginLoc();
+}
+
+SourceLocation CXXFunctionalCastExpr::getEndLoc() const {
+ return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getEndLoc();
+}
+
+UserDefinedLiteral::UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args,
+ QualType Ty, ExprValueKind VK,
+ SourceLocation LitEndLoc,
+ SourceLocation SuffixLoc)
+ : CallExpr(UserDefinedLiteralClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
+ LitEndLoc, /*MinNumArgs=*/0, NotADL),
+ UDSuffixLoc(SuffixLoc) {}
+
+UserDefinedLiteral::UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
+
+UserDefinedLiteral *UserDefinedLiteral::Create(const ASTContext &Ctx, Expr *Fn,
+ ArrayRef<Expr *> Args,
+ QualType Ty, ExprValueKind VK,
+ SourceLocation LitEndLoc,
+ SourceLocation SuffixLoc) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned NumArgs = Args.size();
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects,
+ alignof(UserDefinedLiteral));
+ return new (Mem) UserDefinedLiteral(Fn, Args, Ty, VK, LitEndLoc, SuffixLoc);
+}
+
+UserDefinedLiteral *UserDefinedLiteral::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs,
+ EmptyShell Empty) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects,
+ alignof(UserDefinedLiteral));
+ return new (Mem) UserDefinedLiteral(NumArgs, Empty);
+}
+
+UserDefinedLiteral::LiteralOperatorKind
+UserDefinedLiteral::getLiteralOperatorKind() const {
+ if (getNumArgs() == 0)
+ return LOK_Template;
+ if (getNumArgs() == 2)
+ return LOK_String;
+
+ assert(getNumArgs() == 1 && "unexpected #args in literal operator call");
+ QualType ParamTy =
+ cast<FunctionDecl>(getCalleeDecl())->getParamDecl(0)->getType();
+ if (ParamTy->isPointerType())
+ return LOK_Raw;
+ if (ParamTy->isAnyCharacterType())
+ return LOK_Character;
+ if (ParamTy->isIntegerType())
+ return LOK_Integer;
+ if (ParamTy->isFloatingType())
+ return LOK_Floating;
+
+ llvm_unreachable("unknown kind of literal operator");
+}
+
+Expr *UserDefinedLiteral::getCookedLiteral() {
+#ifndef NDEBUG
+ LiteralOperatorKind LOK = getLiteralOperatorKind();
+ assert(LOK != LOK_Template && LOK != LOK_Raw && "not a cooked literal");
+#endif
+ return getArg(0);
+}
+
+const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const {
+ return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier();
+}
+
+CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc,
+ FieldDecl *Field, QualType Ty,
+ DeclContext *UsedContext)
+ : Expr(CXXDefaultInitExprClass, Ty.getNonLValueExprType(Ctx),
+ Ty->isLValueReferenceType() ? VK_LValue : Ty->isRValueReferenceType()
+ ? VK_XValue
+ : VK_RValue,
+ /*FIXME*/ OK_Ordinary, false, false, false, false),
+ Field(Field), UsedContext(UsedContext) {
+ CXXDefaultInitExprBits.Loc = Loc;
+ assert(Field->hasInClassInitializer());
+}
+
+CXXTemporary *CXXTemporary::Create(const ASTContext &C,
+ const CXXDestructorDecl *Destructor) {
+ return new (C) CXXTemporary(Destructor);
+}
+
+CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(const ASTContext &C,
+ CXXTemporary *Temp,
+ Expr* SubExpr) {
+ assert((SubExpr->getType()->isRecordType() ||
+ SubExpr->getType()->isArrayType()) &&
+ "Expression bound to a temporary must have record or array type!");
+
+ return new (C) CXXBindTemporaryExpr(Temp, SubExpr);
+}
+
+CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(
+ CXXConstructorDecl *Cons, QualType Ty, TypeSourceInfo *TSI,
+ ArrayRef<Expr *> Args, SourceRange ParenOrBraceRange,
+ bool HadMultipleCandidates, bool ListInitialization,
+ bool StdInitListInitialization, bool ZeroInitialization)
+ : CXXConstructExpr(
+ CXXTemporaryObjectExprClass, Ty, TSI->getTypeLoc().getBeginLoc(),
+ Cons, /* Elidable=*/false, Args, HadMultipleCandidates,
+ ListInitialization, StdInitListInitialization, ZeroInitialization,
+ CXXConstructExpr::CK_Complete, ParenOrBraceRange),
+ TSI(TSI) {}
+
+CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(EmptyShell Empty,
+ unsigned NumArgs)
+ : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty, NumArgs) {}
+
+CXXTemporaryObjectExpr *CXXTemporaryObjectExpr::Create(
+ const ASTContext &Ctx, CXXConstructorDecl *Cons, QualType Ty,
+ TypeSourceInfo *TSI, ArrayRef<Expr *> Args, SourceRange ParenOrBraceRange,
+ bool HadMultipleCandidates, bool ListInitialization,
+ bool StdInitListInitialization, bool ZeroInitialization) {
+ unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(Args.size());
+ void *Mem =
+ Ctx.Allocate(sizeof(CXXTemporaryObjectExpr) + SizeOfTrailingObjects,
+ alignof(CXXTemporaryObjectExpr));
+ return new (Mem) CXXTemporaryObjectExpr(
+ Cons, Ty, TSI, Args, ParenOrBraceRange, HadMultipleCandidates,
+ ListInitialization, StdInitListInitialization, ZeroInitialization);
+}
+
+CXXTemporaryObjectExpr *
+CXXTemporaryObjectExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs) {
+ unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(NumArgs);
+ void *Mem =
+ Ctx.Allocate(sizeof(CXXTemporaryObjectExpr) + SizeOfTrailingObjects,
+ alignof(CXXTemporaryObjectExpr));
+ return new (Mem) CXXTemporaryObjectExpr(EmptyShell(), NumArgs);
+}
+
+SourceLocation CXXTemporaryObjectExpr::getBeginLoc() const {
+ return getTypeSourceInfo()->getTypeLoc().getBeginLoc();
+}
+
+SourceLocation CXXTemporaryObjectExpr::getEndLoc() const {
+ SourceLocation Loc = getParenOrBraceRange().getEnd();
+ if (Loc.isInvalid() && getNumArgs())
+ Loc = getArg(getNumArgs() - 1)->getEndLoc();
+ return Loc;
+}
+
+CXXConstructExpr *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) {
+ unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(Args.size());
+ void *Mem = Ctx.Allocate(sizeof(CXXConstructExpr) + SizeOfTrailingObjects,
+ alignof(CXXConstructExpr));
+ return new (Mem) CXXConstructExpr(
+ CXXConstructExprClass, Ty, Loc, Ctor, Elidable, Args,
+ HadMultipleCandidates, ListInitialization, StdInitListInitialization,
+ ZeroInitialization, ConstructKind, ParenOrBraceRange);
+}
+
+CXXConstructExpr *CXXConstructExpr::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs) {
+ unsigned SizeOfTrailingObjects = sizeOfTrailingObjects(NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CXXConstructExpr) + SizeOfTrailingObjects,
+ alignof(CXXConstructExpr));
+ return new (Mem)
+ CXXConstructExpr(CXXConstructExprClass, EmptyShell(), NumArgs);
+}
+
+CXXConstructExpr::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)
+ : Expr(SC, Ty, VK_RValue, OK_Ordinary, Ty->isDependentType(),
+ Ty->isDependentType(), Ty->isInstantiationDependentType(),
+ Ty->containsUnexpandedParameterPack()),
+ Constructor(Ctor), ParenOrBraceRange(ParenOrBraceRange),
+ NumArgs(Args.size()) {
+ CXXConstructExprBits.Elidable = Elidable;
+ CXXConstructExprBits.HadMultipleCandidates = HadMultipleCandidates;
+ CXXConstructExprBits.ListInitialization = ListInitialization;
+ CXXConstructExprBits.StdInitListInitialization = StdInitListInitialization;
+ CXXConstructExprBits.ZeroInitialization = ZeroInitialization;
+ CXXConstructExprBits.ConstructionKind = ConstructKind;
+ CXXConstructExprBits.Loc = Loc;
+
+ Stmt **TrailingArgs = getTrailingArgs();
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ assert(Args[I] && "NULL argument in CXXConstructExpr!");
+
+ if (Args[I]->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (Args[I]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (Args[I]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ TrailingArgs[I] = Args[I];
+ }
+}
+
+CXXConstructExpr::CXXConstructExpr(StmtClass SC, EmptyShell Empty,
+ unsigned NumArgs)
+ : Expr(SC, Empty), NumArgs(NumArgs) {}
+
+LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
+ LambdaCaptureKind Kind, VarDecl *Var,
+ SourceLocation EllipsisLoc)
+ : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc) {
+ unsigned Bits = 0;
+ if (Implicit)
+ Bits |= Capture_Implicit;
+
+ switch (Kind) {
+ case LCK_StarThis:
+ Bits |= Capture_ByCopy;
+ LLVM_FALLTHROUGH;
+ case LCK_This:
+ assert(!Var && "'this' capture cannot have a variable!");
+ Bits |= Capture_This;
+ break;
+
+ case LCK_ByCopy:
+ Bits |= Capture_ByCopy;
+ LLVM_FALLTHROUGH;
+ case LCK_ByRef:
+ assert(Var && "capture must have a variable!");
+ break;
+ case LCK_VLAType:
+ assert(!Var && "VLA type capture cannot have a variable!");
+ break;
+ }
+ DeclAndBits.setInt(Bits);
+}
+
+LambdaCaptureKind LambdaCapture::getCaptureKind() const {
+ if (capturesVLAType())
+ return LCK_VLAType;
+ bool CapByCopy = DeclAndBits.getInt() & Capture_ByCopy;
+ if (capturesThis())
+ return CapByCopy ? LCK_StarThis : LCK_This;
+ return CapByCopy ? LCK_ByCopy : LCK_ByRef;
+}
+
+LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
+ LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
+ ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
+ bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
+ SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack)
+ : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(),
+ T->isDependentType(), T->isDependentType(),
+ ContainsUnexpandedParameterPack),
+ IntroducerRange(IntroducerRange), CaptureDefaultLoc(CaptureDefaultLoc),
+ NumCaptures(Captures.size()), CaptureDefault(CaptureDefault),
+ ExplicitParams(ExplicitParams), ExplicitResultType(ExplicitResultType),
+ ClosingBrace(ClosingBrace) {
+ assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
+ CXXRecordDecl *Class = getLambdaClass();
+ CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData();
+
+ // FIXME: Propagate "has unexpanded parameter pack" bit.
+
+ // Copy captures.
+ const ASTContext &Context = Class->getASTContext();
+ Data.NumCaptures = NumCaptures;
+ Data.NumExplicitCaptures = 0;
+ Data.Captures =
+ (LambdaCapture *)Context.Allocate(sizeof(LambdaCapture) * NumCaptures);
+ LambdaCapture *ToCapture = Data.Captures;
+ for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
+ if (Captures[I].isExplicit())
+ ++Data.NumExplicitCaptures;
+
+ *ToCapture++ = Captures[I];
+ }
+
+ // Copy initialization expressions for the non-static data members.
+ Stmt **Stored = getStoredStmts();
+ for (unsigned I = 0, N = CaptureInits.size(); I != N; ++I)
+ *Stored++ = CaptureInits[I];
+
+ // Copy the body of the lambda.
+ *Stored++ = getCallOperator()->getBody();
+}
+
+LambdaExpr *LambdaExpr::Create(
+ const ASTContext &Context, CXXRecordDecl *Class,
+ SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
+ bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
+ SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) {
+ // Determine the type of the expression (i.e., the type of the
+ // function object we're creating).
+ QualType T = Context.getTypeDeclType(Class);
+
+ unsigned Size = totalSizeToAlloc<Stmt *>(Captures.size() + 1);
+ void *Mem = Context.Allocate(Size);
+ return new (Mem)
+ LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc,
+ Captures, ExplicitParams, ExplicitResultType, CaptureInits,
+ ClosingBrace, ContainsUnexpandedParameterPack);
+}
+
+LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
+ unsigned NumCaptures) {
+ unsigned Size = totalSizeToAlloc<Stmt *>(NumCaptures + 1);
+ void *Mem = C.Allocate(Size);
+ return new (Mem) LambdaExpr(EmptyShell(), NumCaptures);
+}
+
+bool LambdaExpr::isInitCapture(const LambdaCapture *C) const {
+ return (C->capturesVariable() && C->getCapturedVar()->isInitCapture() &&
+ (getCallOperator() == C->getCapturedVar()->getDeclContext()));
+}
+
+LambdaExpr::capture_iterator LambdaExpr::capture_begin() const {
+ return getLambdaClass()->getLambdaData().Captures;
+}
+
+LambdaExpr::capture_iterator LambdaExpr::capture_end() const {
+ return capture_begin() + NumCaptures;
+}
+
+LambdaExpr::capture_range LambdaExpr::captures() const {
+ return capture_range(capture_begin(), capture_end());
+}
+
+LambdaExpr::capture_iterator LambdaExpr::explicit_capture_begin() const {
+ return capture_begin();
+}
+
+LambdaExpr::capture_iterator LambdaExpr::explicit_capture_end() const {
+ struct CXXRecordDecl::LambdaDefinitionData &Data
+ = getLambdaClass()->getLambdaData();
+ return Data.Captures + Data.NumExplicitCaptures;
+}
+
+LambdaExpr::capture_range LambdaExpr::explicit_captures() const {
+ return capture_range(explicit_capture_begin(), explicit_capture_end());
+}
+
+LambdaExpr::capture_iterator LambdaExpr::implicit_capture_begin() const {
+ return explicit_capture_end();
+}
+
+LambdaExpr::capture_iterator LambdaExpr::implicit_capture_end() const {
+ return capture_end();
+}
+
+LambdaExpr::capture_range LambdaExpr::implicit_captures() const {
+ return capture_range(implicit_capture_begin(), implicit_capture_end());
+}
+
+CXXRecordDecl *LambdaExpr::getLambdaClass() const {
+ return getType()->getAsCXXRecordDecl();
+}
+
+CXXMethodDecl *LambdaExpr::getCallOperator() const {
+ CXXRecordDecl *Record = getLambdaClass();
+ return Record->getLambdaCallOperator();
+}
+
+FunctionTemplateDecl *LambdaExpr::getDependentCallOperator() const {
+ CXXRecordDecl *Record = getLambdaClass();
+ return Record->getDependentLambdaCallOperator();
+}
+
+TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
+ CXXRecordDecl *Record = getLambdaClass();
+ return Record->getGenericLambdaTemplateParameterList();
+}
+
+ArrayRef<NamedDecl *> LambdaExpr::getExplicitTemplateParameters() const {
+ const CXXRecordDecl *Record = getLambdaClass();
+ return Record->getLambdaExplicitTemplateParameters();
+}
+
+CompoundStmt *LambdaExpr::getBody() const {
+ // FIXME: this mutation in getBody is bogus. It should be
+ // initialized in ASTStmtReader::VisitLambdaExpr, but for reasons I
+ // don't understand, that doesn't work.
+ if (!getStoredStmts()[NumCaptures])
+ *const_cast<Stmt **>(&getStoredStmts()[NumCaptures]) =
+ getCallOperator()->getBody();
+
+ return static_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
+}
+
+bool LambdaExpr::isMutable() const {
+ return !getCallOperator()->isConst();
+}
+
+ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
+ bool CleanupsHaveSideEffects,
+ ArrayRef<CleanupObject> objects)
+ : FullExpr(ExprWithCleanupsClass, subexpr) {
+ ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects;
+ ExprWithCleanupsBits.NumObjects = objects.size();
+ for (unsigned i = 0, e = objects.size(); i != e; ++i)
+ getTrailingObjects<CleanupObject>()[i] = objects[i];
+}
+
+ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr,
+ bool CleanupsHaveSideEffects,
+ ArrayRef<CleanupObject> objects) {
+ void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()),
+ alignof(ExprWithCleanups));
+ return new (buffer)
+ ExprWithCleanups(subexpr, CleanupsHaveSideEffects, objects);
+}
+
+ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects)
+ : FullExpr(ExprWithCleanupsClass, empty) {
+ ExprWithCleanupsBits.NumObjects = numObjects;
+}
+
+ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C,
+ EmptyShell empty,
+ unsigned numObjects) {
+ void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(numObjects),
+ alignof(ExprWithCleanups));
+ return new (buffer) ExprWithCleanups(empty, numObjects);
+}
+
+CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *TSI,
+ SourceLocation LParenLoc,
+ ArrayRef<Expr *> Args,
+ SourceLocation RParenLoc)
+ : Expr(CXXUnresolvedConstructExprClass,
+ TSI->getType().getNonReferenceType(),
+ (TSI->getType()->isLValueReferenceType()
+ ? VK_LValue
+ : TSI->getType()->isRValueReferenceType() ? VK_XValue
+ : VK_RValue),
+ OK_Ordinary,
+ TSI->getType()->isDependentType() ||
+ TSI->getType()->getContainedDeducedType(),
+ true, true, TSI->getType()->containsUnexpandedParameterPack()),
+ TSI(TSI), LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
+ CXXUnresolvedConstructExprBits.NumArgs = Args.size();
+ auto **StoredArgs = getTrailingObjects<Expr *>();
+ for (unsigned I = 0; I != Args.size(); ++I) {
+ if (Args[I]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ StoredArgs[I] = Args[I];
+ }
+}
+
+CXXUnresolvedConstructExpr *CXXUnresolvedConstructExpr::Create(
+ const ASTContext &Context, TypeSourceInfo *TSI, SourceLocation LParenLoc,
+ ArrayRef<Expr *> Args, SourceLocation RParenLoc) {
+ void *Mem = Context.Allocate(totalSizeToAlloc<Expr *>(Args.size()));
+ return new (Mem) CXXUnresolvedConstructExpr(TSI, LParenLoc, Args, RParenLoc);
+}
+
+CXXUnresolvedConstructExpr *
+CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &Context,
+ unsigned NumArgs) {
+ void *Mem = Context.Allocate(totalSizeToAlloc<Expr *>(NumArgs));
+ return new (Mem) CXXUnresolvedConstructExpr(EmptyShell(), NumArgs);
+}
+
+SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const {
+ return TSI->getTypeLoc().getBeginLoc();
+}
+
+CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
+ const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs)
+ : Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue,
+ OK_Ordinary, true, true, true,
+ ((Base && Base->containsUnexpandedParameterPack()) ||
+ (QualifierLoc && QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()) ||
+ MemberNameInfo.containsUnexpandedParameterPack())),
+ Base(Base), BaseType(BaseType), QualifierLoc(QualifierLoc),
+ MemberNameInfo(MemberNameInfo) {
+ CXXDependentScopeMemberExprBits.IsArrow = IsArrow;
+ CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
+ (TemplateArgs != nullptr) || TemplateKWLoc.isValid();
+ CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
+ FirstQualifierFoundInScope != nullptr;
+ CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;
+
+ if (TemplateArgs) {
+ bool Dependent = true;
+ bool InstantiationDependent = true;
+ bool ContainsUnexpandedParameterPack = false;
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
+ Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
+ if (ContainsUnexpandedParameterPack)
+ ExprBits.ContainsUnexpandedParameterPack = true;
+ } else if (TemplateKWLoc.isValid()) {
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc);
+ }
+
+ if (hasFirstQualifierFoundInScope())
+ *getTrailingObjects<NamedDecl *>() = FirstQualifierFoundInScope;
+}
+
+CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
+ EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
+ bool HasFirstQualifierFoundInScope)
+ : Expr(CXXDependentScopeMemberExprClass, Empty) {
+ CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
+ HasTemplateKWAndArgsInfo;
+ CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
+ HasFirstQualifierFoundInScope;
+}
+
+CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::Create(
+ const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ bool HasTemplateKWAndArgsInfo =
+ (TemplateArgs != nullptr) || TemplateKWLoc.isValid();
+ unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
+ bool HasFirstQualifierFoundInScope = FirstQualifierFoundInScope != nullptr;
+
+ unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc, NamedDecl *>(
+ HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
+
+ void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
+ return new (Mem) CXXDependentScopeMemberExpr(
+ Ctx, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc,
+ FirstQualifierFoundInScope, MemberNameInfo, TemplateArgs);
+}
+
+CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::CreateEmpty(
+ const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope) {
+ assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
+
+ unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc, NamedDecl *>(
+ HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
+
+ void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
+ return new (Mem) CXXDependentScopeMemberExpr(
+ EmptyShell(), HasTemplateKWAndArgsInfo, HasFirstQualifierFoundInScope);
+}
+
+static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin,
+ UnresolvedSetIterator end) {
+ do {
+ NamedDecl *decl = *begin;
+ if (isa<UnresolvedUsingValueDecl>(decl))
+ return false;
+
+ // Unresolved member expressions should only contain methods and
+ // method templates.
+ if (cast<CXXMethodDecl>(decl->getUnderlyingDecl()->getAsFunction())
+ ->isStatic())
+ return false;
+ } while (++begin != end);
+
+ return true;
+}
+
+UnresolvedMemberExpr::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)
+ : OverloadExpr(
+ UnresolvedMemberExprClass, Context, QualifierLoc, TemplateKWLoc,
+ MemberNameInfo, TemplateArgs, Begin, End,
+ // Dependent
+ ((Base && Base->isTypeDependent()) || BaseType->isDependentType()),
+ ((Base && Base->isInstantiationDependent()) ||
+ BaseType->isInstantiationDependentType()),
+ // Contains unexpanded parameter pack
+ ((Base && Base->containsUnexpandedParameterPack()) ||
+ BaseType->containsUnexpandedParameterPack())),
+ Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) {
+ UnresolvedMemberExprBits.IsArrow = IsArrow;
+ UnresolvedMemberExprBits.HasUnresolvedUsing = HasUnresolvedUsing;
+
+ // Check whether all of the members are non-static member functions,
+ // and if so, mark give this bound-member type instead of overload type.
+ if (hasOnlyNonStaticMemberFunctions(Begin, End))
+ setType(Context.BoundMemberTy);
+}
+
+UnresolvedMemberExpr::UnresolvedMemberExpr(EmptyShell Empty,
+ unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo)
+ : OverloadExpr(UnresolvedMemberExprClass, Empty, NumResults,
+ HasTemplateKWAndArgsInfo) {}
+
+bool UnresolvedMemberExpr::isImplicitAccess() const {
+ if (!Base)
+ return true;
+
+ return cast<Expr>(Base)->isImplicitCXXThis();
+}
+
+UnresolvedMemberExpr *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) {
+ unsigned NumResults = End - Begin;
+ bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
+ unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
+ unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(
+ NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ void *Mem = Context.Allocate(Size, alignof(UnresolvedMemberExpr));
+ return new (Mem) UnresolvedMemberExpr(
+ Context, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc,
+ QualifierLoc, TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End);
+}
+
+UnresolvedMemberExpr *UnresolvedMemberExpr::CreateEmpty(
+ const ASTContext &Context, unsigned NumResults,
+ bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) {
+ assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
+ unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(
+ NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ void *Mem = Context.Allocate(Size, alignof(UnresolvedMemberExpr));
+ return new (Mem)
+ UnresolvedMemberExpr(EmptyShell(), NumResults, HasTemplateKWAndArgsInfo);
+}
+
+CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() {
+ // Unlike for UnresolvedLookupExpr, it is very easy to re-derive this.
+
+ // If there was a nested name specifier, it names the naming class.
+ // It can't be dependent: after all, we were actually able to do the
+ // lookup.
+ CXXRecordDecl *Record = nullptr;
+ auto *NNS = getQualifier();
+ if (NNS && NNS->getKind() != NestedNameSpecifier::Super) {
+ const Type *T = getQualifier()->getAsType();
+ assert(T && "qualifier in member expression does not name type");
+ Record = T->getAsCXXRecordDecl();
+ assert(Record && "qualifier in member expression does not name record");
+ }
+ // Otherwise the naming class must have been the base class.
+ else {
+ QualType BaseType = getBaseType().getNonReferenceType();
+ if (isArrow())
+ BaseType = BaseType->castAs<PointerType>()->getPointeeType();
+
+ Record = BaseType->getAsCXXRecordDecl();
+ assert(Record && "base of member expression does not name record");
+ }
+
+ return Record;
+}
+
+SizeOfPackExpr *
+SizeOfPackExpr::Create(ASTContext &Context, SourceLocation OperatorLoc,
+ NamedDecl *Pack, SourceLocation PackLoc,
+ SourceLocation RParenLoc,
+ Optional<unsigned> Length,
+ ArrayRef<TemplateArgument> PartialArgs) {
+ void *Storage =
+ Context.Allocate(totalSizeToAlloc<TemplateArgument>(PartialArgs.size()));
+ return new (Storage) SizeOfPackExpr(Context.getSizeType(), OperatorLoc, Pack,
+ PackLoc, RParenLoc, Length, PartialArgs);
+}
+
+SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
+ unsigned NumPartialArgs) {
+ void *Storage =
+ Context.Allocate(totalSizeToAlloc<TemplateArgument>(NumPartialArgs));
+ return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs);
+}
+
+SubstNonTypeTemplateParmPackExpr::
+SubstNonTypeTemplateParmPackExpr(QualType T,
+ ExprValueKind ValueKind,
+ NonTypeTemplateParmDecl *Param,
+ SourceLocation NameLoc,
+ const TemplateArgument &ArgPack)
+ : Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary,
+ true, true, true, true),
+ Param(Param), Arguments(ArgPack.pack_begin()),
+ NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) {}
+
+TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
+ return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments));
+}
+
+FunctionParmPackExpr::FunctionParmPackExpr(QualType T, VarDecl *ParamPack,
+ SourceLocation NameLoc,
+ unsigned NumParams,
+ VarDecl *const *Params)
+ : Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary, true, true,
+ true, true),
+ ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) {
+ if (Params)
+ std::uninitialized_copy(Params, Params + NumParams,
+ getTrailingObjects<VarDecl *>());
+}
+
+FunctionParmPackExpr *
+FunctionParmPackExpr::Create(const ASTContext &Context, QualType T,
+ VarDecl *ParamPack, SourceLocation NameLoc,
+ ArrayRef<VarDecl *> Params) {
+ return new (Context.Allocate(totalSizeToAlloc<VarDecl *>(Params.size())))
+ FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data());
+}
+
+FunctionParmPackExpr *
+FunctionParmPackExpr::CreateEmpty(const ASTContext &Context,
+ unsigned NumParams) {
+ return new (Context.Allocate(totalSizeToAlloc<VarDecl *>(NumParams)))
+ FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr);
+}
+
+void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy,
+ unsigned ManglingNumber) {
+ // We only need extra state if we have to remember more than just the Stmt.
+ if (!ExtendedBy)
+ return;
+
+ // We may need to allocate extra storage for the mangling number and the
+ // extended-by ValueDecl.
+ if (!State.is<ExtraState *>()) {
+ auto *ES = new (ExtendedBy->getASTContext()) ExtraState;
+ ES->Temporary = State.get<Stmt *>();
+ State = ES;
+ }
+
+ auto ES = State.get<ExtraState *>();
+ ES->ExtendingDecl = ExtendedBy;
+ ES->ManglingNumber = ManglingNumber;
+}
+
+TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
+ ArrayRef<TypeSourceInfo *> Args,
+ SourceLocation RParenLoc,
+ bool Value)
+ : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false,
+ /*ValueDependent=*/false,
+ /*InstantiationDependent=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ Loc(Loc), RParenLoc(RParenLoc) {
+ TypeTraitExprBits.Kind = Kind;
+ TypeTraitExprBits.Value = Value;
+ TypeTraitExprBits.NumArgs = Args.size();
+
+ auto **ToArgs = getTrailingObjects<TypeSourceInfo *>();
+
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ if (Args[I]->getType()->isDependentType())
+ setValueDependent(true);
+ if (Args[I]->getType()->isInstantiationDependentType())
+ setInstantiationDependent(true);
+ if (Args[I]->getType()->containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack(true);
+
+ ToArgs[I] = Args[I];
+ }
+}
+
+TypeTraitExpr *TypeTraitExpr::Create(const ASTContext &C, QualType T,
+ SourceLocation Loc,
+ TypeTrait Kind,
+ ArrayRef<TypeSourceInfo *> Args,
+ SourceLocation RParenLoc,
+ bool Value) {
+ void *Mem = C.Allocate(totalSizeToAlloc<TypeSourceInfo *>(Args.size()));
+ return new (Mem) TypeTraitExpr(T, Loc, Kind, Args, RParenLoc, Value);
+}
+
+TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C,
+ unsigned NumArgs) {
+ void *Mem = C.Allocate(totalSizeToAlloc<TypeSourceInfo *>(NumArgs));
+ return new (Mem) TypeTraitExpr(EmptyShell());
+}
+
+CUDAKernelCallExpr::CUDAKernelCallExpr(Expr *Fn, CallExpr *Config,
+ ArrayRef<Expr *> Args, QualType Ty,
+ ExprValueKind VK, SourceLocation RP,
+ unsigned MinNumArgs)
+ : CallExpr(CUDAKernelCallExprClass, Fn, /*PreArgs=*/Config, Args, Ty, VK,
+ RP, MinNumArgs, NotADL) {}
+
+CUDAKernelCallExpr::CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(CUDAKernelCallExprClass, /*NumPreArgs=*/END_PREARG, NumArgs,
+ Empty) {}
+
+CUDAKernelCallExpr *
+CUDAKernelCallExpr::Create(const ASTContext &Ctx, Expr *Fn, CallExpr *Config,
+ ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+ SourceLocation RP, unsigned MinNumArgs) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/END_PREARG, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects,
+ alignof(CUDAKernelCallExpr));
+ return new (Mem) CUDAKernelCallExpr(Fn, Config, Args, Ty, VK, RP, MinNumArgs);
+}
+
+CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx,
+ unsigned NumArgs,
+ EmptyShell Empty) {
+ // Allocate storage for the trailing objects of CallExpr.
+ unsigned SizeOfTrailingObjects =
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/END_PREARG, NumArgs);
+ void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects,
+ alignof(CUDAKernelCallExpr));
+ return new (Mem) CUDAKernelCallExpr(NumArgs, Empty);
+}
+
+ConceptSpecializationExpr::ConceptSpecializationExpr(ASTContext &C,
+ NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
+ SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
+ ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied)
+ : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false,
+ // All the flags below are set in setTemplateArguments.
+ /*ValueDependent=*/!IsSatisfied.hasValue(),
+ /*InstantiationDependent=*/false,
+ /*ContainsUnexpandedParameterPacks=*/false),
+ NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
+ ConceptNameLoc(ConceptNameLoc), FoundDecl(FoundDecl),
+ NamedConcept(NamedConcept, IsSatisfied ? *IsSatisfied : true),
+ NumTemplateArgs(ConvertedArgs.size()) {
+
+ setTemplateArguments(ArgsAsWritten, ConvertedArgs);
+}
+
+ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
+ unsigned NumTemplateArgs)
+ : Expr(ConceptSpecializationExprClass, Empty),
+ NumTemplateArgs(NumTemplateArgs) { }
+
+void ConceptSpecializationExpr::setTemplateArguments(
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ArrayRef<TemplateArgument> Converted) {
+ assert(Converted.size() == NumTemplateArgs);
+ assert(!this->ArgsAsWritten && "setTemplateArguments can only be used once");
+ this->ArgsAsWritten = ArgsAsWritten;
+ std::uninitialized_copy(Converted.begin(), Converted.end(),
+ getTrailingObjects<TemplateArgument>());
+ bool IsInstantiationDependent = false;
+ bool ContainsUnexpandedParameterPack = false;
+ for (const TemplateArgumentLoc& LocInfo : ArgsAsWritten->arguments()) {
+ if (LocInfo.getArgument().isInstantiationDependent())
+ IsInstantiationDependent = true;
+ if (LocInfo.getArgument().containsUnexpandedParameterPack())
+ ContainsUnexpandedParameterPack = true;
+ if (ContainsUnexpandedParameterPack && IsInstantiationDependent)
+ break;
+ }
+
+ // Currently guaranteed by the fact concepts can only be at namespace-scope.
+ assert(!NestedNameSpec ||
+ (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
+ !NestedNameSpec.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()));
+ setInstantiationDependent(IsInstantiationDependent);
+ setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);
+ assert((!isValueDependent() || isInstantiationDependent()) &&
+ "should not be value-dependent");
+}
+
+ConceptSpecializationExpr *
+ConceptSpecializationExpr::Create(ASTContext &C, NestedNameSpecifierLoc NNS,
+ SourceLocation TemplateKWLoc,
+ SourceLocation ConceptNameLoc,
+ NamedDecl *FoundDecl,
+ ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ Optional<bool> IsSatisfied) {
+ void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
+ ConvertedArgs.size()));
+ return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
+ ConceptNameLoc, FoundDecl,
+ NamedConcept, ArgsAsWritten,
+ ConvertedArgs, IsSatisfied);
+}
+
+ConceptSpecializationExpr *
+ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
+ unsigned NumTemplateArgs) {
+ void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
+ NumTemplateArgs));
+ return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
+}