diff options
Diffstat (limited to 'clang/lib/AST/ExprCXX.cpp')
| -rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 1831 |
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); +} |
