2017-11-18 09:47:41 +08:00
|
|
|
//===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===//
|
2007-08-25 04:21:10 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2007-08-25 04:21:10 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the subclesses of Expr class declared in ExprCXX.h
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-11-18 09:47:41 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2012-07-05 04:19:54 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/Attr.h"
|
2017-11-18 09:47:41 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/AST/DeclAccessPair.h"
|
|
|
|
#include "clang/AST/DeclBase.h"
|
2008-11-15 00:09:21 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2017-11-18 09:47:41 +08:00
|
|
|
#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"
|
2010-02-25 07:40:28 +08:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2017-11-18 09:47:41 +08:00
|
|
|
#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>
|
2007-08-25 04:21:10 +08:00
|
|
|
|
2017-11-18 09:47:41 +08:00
|
|
|
using namespace clang;
|
2010-04-27 06:37:10 +08:00
|
|
|
|
2007-08-25 04:21:10 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Child Iterators for iterating over subexpressions/substatements
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-10-20 08:55:15 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-14 04:08:14 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-09-27 15:04:31 +08:00
|
|
|
QualType CXXTypeidExpr::getTypeOperand(ASTContext &Context) const {
|
2010-04-27 06:37:10 +08:00
|
|
|
assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
|
2013-09-27 15:04:31 +08:00
|
|
|
Qualifiers Quals;
|
|
|
|
return Context.getUnqualifiedArrayType(
|
|
|
|
Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType(), Quals);
|
2010-04-27 06:37:10 +08:00
|
|
|
}
|
|
|
|
|
2013-09-27 15:04:31 +08:00
|
|
|
QualType CXXUuidofExpr::getTypeOperand(ASTContext &Context) const {
|
2010-09-08 20:20:18 +08:00
|
|
|
assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
|
2013-09-27 15:04:31 +08:00
|
|
|
Qualifiers Quals;
|
|
|
|
return Context.getUnqualifiedArrayType(
|
|
|
|
Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType(), Quals);
|
2010-09-08 20:20:18 +08:00
|
|
|
}
|
|
|
|
|
2010-07-08 14:14:04 +08:00
|
|
|
// CXXScalarValueInitExpr
|
2018-08-10 04:05:03 +08:00
|
|
|
SourceLocation CXXScalarValueInitExpr::getBeginLoc() const {
|
2019-01-09 00:08:54 +08:00
|
|
|
return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : getRParenLoc();
|
2010-09-08 08:15:04 +08:00
|
|
|
}
|
|
|
|
|
2008-11-22 03:14:01 +08:00
|
|
|
// CXXNewExpr
|
2019-01-07 23:04:45 +08:00
|
|
|
CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
|
|
|
|
FunctionDecl *OperatorDelete, bool ShouldPassAlignment,
|
|
|
|
bool UsualArrayDeleteWantsSize,
|
|
|
|
ArrayRef<Expr *> PlacementArgs, SourceRange TypeIdParens,
|
2019-05-06 11:47:15 +08:00
|
|
|
Optional<Expr *> ArraySize,
|
|
|
|
InitializationStyle InitializationStyle,
|
2019-01-07 23:04:45 +08:00
|
|
|
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;
|
2019-05-06 11:47:15 +08:00
|
|
|
CXXNewExprBits.IsArray = ArraySize.hasValue();
|
2019-01-07 23:04:45 +08:00
|
|
|
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) {
|
2019-05-06 11:47:15 +08:00
|
|
|
if (Expr *SizeExpr = *ArraySize) {
|
|
|
|
if (SizeExpr->isInstantiationDependent())
|
|
|
|
ExprBits.InstantiationDependent = true;
|
|
|
|
if (SizeExpr->containsUnexpandedParameterPack())
|
|
|
|
ExprBits.ContainsUnexpandedParameterPack = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
getTrailingObjects<Stmt *>()[arraySizeOffset()] = *ArraySize;
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 23:04:45 +08:00
|
|
|
if (Initializer) {
|
|
|
|
if (Initializer->isInstantiationDependent())
|
2011-07-01 09:22:09 +08:00
|
|
|
ExprBits.InstantiationDependent = true;
|
2019-01-07 23:04:45 +08:00
|
|
|
if (Initializer->containsUnexpandedParameterPack())
|
2010-12-15 09:34:56 +08:00
|
|
|
ExprBits.ContainsUnexpandedParameterPack = true;
|
|
|
|
|
2019-01-07 23:04:45 +08:00
|
|
|
getTrailingObjects<Stmt *>()[initExprOffset()] = Initializer;
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 23:04:45 +08:00
|
|
|
for (unsigned I = 0; I != PlacementArgs.size(); ++I) {
|
|
|
|
if (PlacementArgs[I]->isInstantiationDependent())
|
2011-07-01 09:22:09 +08:00
|
|
|
ExprBits.InstantiationDependent = true;
|
2019-01-07 23:04:45 +08:00
|
|
|
if (PlacementArgs[I]->containsUnexpandedParameterPack())
|
2010-12-15 09:34:56 +08:00
|
|
|
ExprBits.ContainsUnexpandedParameterPack = true;
|
|
|
|
|
2019-01-07 23:04:45 +08:00
|
|
|
getTrailingObjects<Stmt *>()[placementNewArgsOffset() + I] =
|
|
|
|
PlacementArgs[I];
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
2012-11-09 06:53:48 +08:00
|
|
|
|
2019-01-07 23:04:45 +08:00
|
|
|
if (IsParenTypeId)
|
|
|
|
getTrailingObjects<SourceRange>()[0] = TypeIdParens;
|
|
|
|
|
2012-11-09 06:53:48 +08:00
|
|
|
switch (getInitializationStyle()) {
|
|
|
|
case CallInit:
|
2019-01-07 23:04:45 +08:00
|
|
|
this->Range.setEnd(DirectInitRange.getEnd());
|
|
|
|
break;
|
2012-11-09 06:53:48 +08:00
|
|
|
case ListInit:
|
2019-01-07 23:04:45 +08:00
|
|
|
this->Range.setEnd(getInitializer()->getSourceRange().getEnd());
|
|
|
|
break;
|
2013-06-18 06:35:10 +08:00
|
|
|
default:
|
2019-01-07 23:04:45 +08:00
|
|
|
if (IsParenTypeId)
|
2013-06-18 06:35:10 +08:00
|
|
|
this->Range.setEnd(TypeIdParens.getEnd());
|
|
|
|
break;
|
2012-11-09 06:53:48 +08:00
|
|
|
}
|
2008-11-22 03:14:01 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 23:04:45 +08:00
|
|
|
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,
|
2019-05-06 11:47:15 +08:00
|
|
|
Optional<Expr *> ArraySize,
|
|
|
|
InitializationStyle InitializationStyle, Expr *Initializer,
|
|
|
|
QualType Ty, TypeSourceInfo *AllocatedTypeInfo,
|
|
|
|
SourceRange Range, SourceRange DirectInitRange) {
|
|
|
|
bool IsArray = ArraySize.hasValue();
|
2019-01-07 23:04:45 +08:00
|
|
|
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);
|
|
|
|
}
|
2012-02-16 20:22:20 +08:00
|
|
|
|
2019-01-07 23:04:45 +08:00
|
|
|
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);
|
2010-05-10 09:22:27 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 23:04:45 +08:00
|
|
|
bool CXXNewExpr::shouldNullCheckAllocation() const {
|
|
|
|
return getOperatorNew()
|
|
|
|
->getType()
|
|
|
|
->castAs<FunctionProtoType>()
|
|
|
|
->isNothrow() &&
|
2015-02-14 09:52:20 +08:00
|
|
|
!getOperatorNew()->isReservedGlobalPlacementOperator();
|
2011-03-07 11:12:35 +08:00
|
|
|
}
|
2010-05-10 09:22:27 +08:00
|
|
|
|
2008-11-22 03:14:01 +08:00
|
|
|
// CXXDeleteExpr
|
2010-09-15 06:55:20 +08:00
|
|
|
QualType CXXDeleteExpr::getDestroyedType() const {
|
|
|
|
const Expr *Arg = getArgument();
|
2017-10-13 09:55:36 +08:00
|
|
|
|
|
|
|
// For a destroying operator delete, we may have implicitly converted the
|
|
|
|
// pointer type to the type of the parameter of the 'operator delete'
|
|
|
|
// function.
|
2018-04-11 06:54:42 +08:00
|
|
|
while (const auto *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
|
2017-10-13 09:55:36 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-10-20 08:38:15 +08:00
|
|
|
// The type-to-delete may not be a pointer if it's a dependent type.
|
2010-10-20 08:56:01 +08:00
|
|
|
const QualType ArgType = Arg->getType();
|
2010-11-16 15:16:25 +08:00
|
|
|
|
|
|
|
if (ArgType->isDependentType() && !ArgType->isPointerType())
|
|
|
|
return QualType();
|
2010-09-15 06:55:20 +08:00
|
|
|
|
2010-10-20 08:38:15 +08:00
|
|
|
return ArgType->getAs<PointerType>()->getPointeeType();
|
2010-09-15 06:55:20 +08:00
|
|
|
}
|
|
|
|
|
2009-09-05 01:36:40 +08:00
|
|
|
// CXXPseudoDestructorExpr
|
2010-02-25 09:56:36 +08:00
|
|
|
PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info)
|
2017-11-18 09:47:41 +08:00
|
|
|
: Type(Info) {
|
2010-05-20 18:00:11 +08:00
|
|
|
Location = Info->getTypeLoc().getLocalSourceRange().getBegin();
|
2010-02-25 09:56:36 +08:00
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context,
|
2011-02-26 02:19:59 +08:00
|
|
|
Expr *Base, bool isArrow, SourceLocation OperatorLoc,
|
2018-07-31 03:24:48 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType,
|
|
|
|
SourceLocation ColonColonLoc, SourceLocation TildeLoc,
|
2011-02-26 02:19:59 +08:00
|
|
|
PseudoDestructorTypeStorage DestroyedType)
|
2010-12-14 16:05:40 +08:00
|
|
|
: Expr(CXXPseudoDestructorExprClass,
|
2015-02-26 01:36:15 +08:00
|
|
|
Context.BoundMemberTy,
|
2010-12-14 16:05:40 +08:00
|
|
|
VK_RValue, OK_Ordinary,
|
|
|
|
/*isTypeDependent=*/(Base->isTypeDependent() ||
|
|
|
|
(DestroyedType.getTypeSourceInfo() &&
|
|
|
|
DestroyedType.getTypeSourceInfo()->getType()->isDependentType())),
|
2010-12-15 09:34:56 +08:00
|
|
|
/*isValueDependent=*/Base->isValueDependent(),
|
2011-07-01 09:22:09 +08:00
|
|
|
(Base->isInstantiationDependent() ||
|
|
|
|
(QualifierLoc &&
|
|
|
|
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) ||
|
|
|
|
(ScopeType &&
|
|
|
|
ScopeType->getType()->isInstantiationDependentType()) ||
|
|
|
|
(DestroyedType.getTypeSourceInfo() &&
|
|
|
|
DestroyedType.getTypeSourceInfo()->getType()
|
|
|
|
->isInstantiationDependentType())),
|
2010-12-15 09:34:56 +08:00
|
|
|
// ContainsUnexpandedParameterPack
|
|
|
|
(Base->containsUnexpandedParameterPack() ||
|
2018-07-31 03:24:48 +08:00
|
|
|
(QualifierLoc &&
|
2011-02-26 02:19:59 +08:00
|
|
|
QualifierLoc.getNestedNameSpecifier()
|
|
|
|
->containsUnexpandedParameterPack()) ||
|
2018-07-31 03:24:48 +08:00
|
|
|
(ScopeType &&
|
2010-12-15 09:34:56 +08:00
|
|
|
ScopeType->getType()->containsUnexpandedParameterPack()) ||
|
|
|
|
(DestroyedType.getTypeSourceInfo() &&
|
|
|
|
DestroyedType.getTypeSourceInfo()->getType()
|
|
|
|
->containsUnexpandedParameterPack()))),
|
2010-12-14 16:05:40 +08:00
|
|
|
Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
|
2011-02-26 02:19:59 +08:00
|
|
|
OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
|
2010-12-14 16:05:40 +08:00
|
|
|
ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc),
|
2017-11-18 09:47:41 +08:00
|
|
|
DestroyedType(DestroyedType) {}
|
2010-12-14 16:05:40 +08:00
|
|
|
|
2010-02-25 09:56:36 +08:00
|
|
|
QualType CXXPseudoDestructorExpr::getDestroyedType() const {
|
|
|
|
if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
|
|
|
|
return TInfo->getType();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-02-25 09:56:36 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2018-08-10 04:05:47 +08:00
|
|
|
SourceLocation CXXPseudoDestructorExpr::getEndLoc() const {
|
2010-02-25 09:56:36 +08:00
|
|
|
SourceLocation End = DestroyedType.getLocation();
|
|
|
|
if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
|
2010-05-20 18:00:11 +08:00
|
|
|
End = TInfo->getTypeLoc().getLocalSourceRange().getEnd();
|
2012-12-25 22:51:39 +08:00
|
|
|
return End;
|
2010-02-25 07:40:28 +08:00
|
|
|
}
|
|
|
|
|
2009-11-21 16:51:07 +08:00
|
|
|
// UnresolvedLookupExpr
|
2019-01-09 23:43:19 +08:00
|
|
|
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);
|
|
|
|
}
|
2015-12-30 02:15:14 +08:00
|
|
|
|
2019-01-09 23:43:19 +08:00
|
|
|
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) {
|
2015-12-30 02:15:14 +08:00
|
|
|
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
|
2019-01-09 23:43:19 +08:00
|
|
|
unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
|
|
|
|
TemplateArgumentLoc>(
|
|
|
|
NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
|
|
|
|
void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
|
|
|
|
return new (Mem)
|
|
|
|
UnresolvedLookupExpr(EmptyShell(), NumResults, HasTemplateKWAndArgsInfo);
|
2010-06-25 17:03:34 +08:00
|
|
|
}
|
|
|
|
|
2019-01-09 23:43:19 +08:00
|
|
|
OverloadExpr::OverloadExpr(StmtClass SC, const ASTContext &Context,
|
2011-03-01 04:01:57 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2012-01-27 17:46:47 +08:00
|
|
|
SourceLocation TemplateKWLoc,
|
2010-08-12 06:01:17 +08:00
|
|
|
const DeclarationNameInfo &NameInfo,
|
2010-12-15 09:34:56 +08:00
|
|
|
const TemplateArgumentListInfo *TemplateArgs,
|
2018-07-31 03:24:48 +08:00
|
|
|
UnresolvedSetIterator Begin,
|
2019-01-09 23:43:19 +08:00
|
|
|
UnresolvedSetIterator End, bool KnownDependent,
|
2011-07-01 09:22:09 +08:00
|
|
|
bool KnownInstantiationDependent,
|
2010-12-15 09:34:56 +08:00
|
|
|
bool KnownContainsUnexpandedParameterPack)
|
2019-01-09 23:43:19 +08:00
|
|
|
: Expr(
|
|
|
|
SC, Context.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent,
|
|
|
|
KnownDependent,
|
|
|
|
(KnownInstantiationDependent || NameInfo.isInstantiationDependent() ||
|
|
|
|
(QualifierLoc &&
|
2017-11-18 09:47:41 +08:00
|
|
|
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
|
2019-01-09 23:43:19 +08:00
|
|
|
(KnownContainsUnexpandedParameterPack ||
|
|
|
|
NameInfo.containsUnexpandedParameterPack() ||
|
|
|
|
(QualifierLoc && QualifierLoc.getNestedNameSpecifier()
|
|
|
|
->containsUnexpandedParameterPack()))),
|
|
|
|
NameInfo(NameInfo), QualifierLoc(QualifierLoc) {
|
|
|
|
unsigned NumResults = End - Begin;
|
|
|
|
OverloadExprBits.NumResults = NumResults;
|
|
|
|
OverloadExprBits.HasTemplateKWAndArgsInfo =
|
|
|
|
(TemplateArgs != nullptr ) || TemplateKWLoc.isValid();
|
|
|
|
|
2010-05-24 03:36:40 +08:00
|
|
|
if (NumResults) {
|
2010-12-15 09:34:56 +08:00
|
|
|
// 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;
|
2012-08-14 05:29:18 +08:00
|
|
|
ExprBits.InstantiationDependent = true;
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-09 23:43:19 +08:00
|
|
|
// Copy the results to the trailing array past UnresolvedLookupExpr
|
|
|
|
// or UnresolvedMemberExpr.
|
|
|
|
DeclAccessPair *Results = getTrailingResults();
|
2015-02-02 04:31:36 +08:00
|
|
|
memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
|
2010-05-24 03:36:40 +08:00
|
|
|
}
|
2010-06-25 17:03:26 +08:00
|
|
|
|
2010-12-15 09:34:56 +08:00
|
|
|
// If we have explicit template arguments, check for dependent
|
|
|
|
// template arguments and whether they contain any unexpanded pack
|
|
|
|
// expansions.
|
|
|
|
if (TemplateArgs) {
|
|
|
|
bool Dependent = false;
|
2011-07-01 09:22:09 +08:00
|
|
|
bool InstantiationDependent = false;
|
2010-12-15 09:34:56 +08:00
|
|
|
bool ContainsUnexpandedParameterPack = false;
|
2015-12-30 02:15:14 +08:00
|
|
|
getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(
|
|
|
|
TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc(),
|
|
|
|
Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
|
2010-12-15 09:34:56 +08:00
|
|
|
|
|
|
|
if (Dependent) {
|
2011-07-01 09:22:09 +08:00
|
|
|
ExprBits.TypeDependent = true;
|
|
|
|
ExprBits.ValueDependent = true;
|
|
|
|
}
|
|
|
|
if (InstantiationDependent)
|
|
|
|
ExprBits.InstantiationDependent = true;
|
2010-12-15 09:34:56 +08:00
|
|
|
if (ContainsUnexpandedParameterPack)
|
|
|
|
ExprBits.ContainsUnexpandedParameterPack = true;
|
2012-01-27 17:46:47 +08:00
|
|
|
} else if (TemplateKWLoc.isValid()) {
|
2015-12-30 02:15:14 +08:00
|
|
|
getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
2009-11-25 03:00:30 +08:00
|
|
|
|
2010-12-15 09:34:56 +08:00
|
|
|
if (isTypeDependent())
|
2019-01-09 23:43:19 +08:00
|
|
|
setType(Context.DependentTy);
|
2009-11-25 03:00:30 +08:00
|
|
|
}
|
|
|
|
|
2019-01-09 23:43:19 +08:00
|
|
|
OverloadExpr::OverloadExpr(StmtClass SC, EmptyShell Empty, unsigned NumResults,
|
|
|
|
bool HasTemplateKWAndArgsInfo)
|
|
|
|
: Expr(SC, Empty) {
|
|
|
|
OverloadExprBits.NumResults = NumResults;
|
|
|
|
OverloadExprBits.HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
|
2010-04-23 02:44:12 +08:00
|
|
|
}
|
|
|
|
|
2009-11-20 06:55:06 +08:00
|
|
|
// DependentScopeDeclRefExpr
|
2019-01-07 22:27:04 +08:00
|
|
|
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();
|
2010-12-15 09:34:56 +08:00
|
|
|
if (Args) {
|
|
|
|
bool Dependent = true;
|
2011-07-01 09:22:09 +08:00
|
|
|
bool InstantiationDependent = true;
|
2010-12-15 09:34:56 +08:00
|
|
|
bool ContainsUnexpandedParameterPack
|
|
|
|
= ExprBits.ContainsUnexpandedParameterPack;
|
2015-12-30 02:15:14 +08:00
|
|
|
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
|
|
|
|
TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>(),
|
|
|
|
Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
|
2010-12-15 09:34:56 +08:00
|
|
|
ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
|
2012-01-27 17:46:47 +08:00
|
|
|
} else if (TemplateKWLoc.isValid()) {
|
2015-12-30 02:15:14 +08:00
|
|
|
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
|
|
|
|
TemplateKWLoc);
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-07 22:27:04 +08:00
|
|
|
DependentScopeDeclRefExpr *DependentScopeDeclRefExpr::Create(
|
|
|
|
const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
|
|
|
|
SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo,
|
|
|
|
const TemplateArgumentListInfo *Args) {
|
2013-10-16 02:38:02 +08:00
|
|
|
assert(QualifierLoc && "should be created for dependent qualifiers");
|
2015-12-30 02:15:14 +08:00
|
|
|
bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid();
|
|
|
|
std::size_t Size =
|
|
|
|
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
|
|
|
|
HasTemplateKWAndArgsInfo, Args ? Args->size() : 0);
|
2019-01-07 22:27:04 +08:00
|
|
|
void *Mem = Context.Allocate(Size);
|
|
|
|
return new (Mem) DependentScopeDeclRefExpr(Context.DependentTy, QualifierLoc,
|
2012-01-27 17:46:47 +08:00
|
|
|
TemplateKWLoc, NameInfo, Args);
|
2009-11-25 03:00:30 +08:00
|
|
|
}
|
|
|
|
|
2010-06-28 17:31:56 +08:00
|
|
|
DependentScopeDeclRefExpr *
|
2019-01-07 22:27:04 +08:00
|
|
|
DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &Context,
|
2012-01-27 17:46:47 +08:00
|
|
|
bool HasTemplateKWAndArgsInfo,
|
2010-06-28 17:31:56 +08:00
|
|
|
unsigned NumTemplateArgs) {
|
2015-12-30 02:15:14 +08:00
|
|
|
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
|
|
|
|
std::size_t Size =
|
|
|
|
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
|
|
|
|
HasTemplateKWAndArgsInfo, NumTemplateArgs);
|
2019-01-07 22:27:04 +08:00
|
|
|
void *Mem = Context.Allocate(Size);
|
|
|
|
auto *E = new (Mem) DependentScopeDeclRefExpr(
|
|
|
|
QualType(), NestedNameSpecifierLoc(), SourceLocation(),
|
|
|
|
DeclarationNameInfo(), nullptr);
|
|
|
|
E->DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
|
|
|
|
HasTemplateKWAndArgsInfo;
|
2011-02-04 20:01:24 +08:00
|
|
|
return E;
|
2010-06-28 17:31:56 +08:00
|
|
|
}
|
|
|
|
|
2018-08-10 04:05:03 +08:00
|
|
|
SourceLocation CXXConstructExpr::getBeginLoc() const {
|
2011-02-21 14:23:05 +08:00
|
|
|
if (isa<CXXTemporaryObjectExpr>(this))
|
2018-08-10 05:08:08 +08:00
|
|
|
return cast<CXXTemporaryObjectExpr>(this)->getBeginLoc();
|
2018-12-22 22:39:30 +08:00
|
|
|
return getLocation();
|
2012-12-25 22:51:39 +08:00
|
|
|
}
|
|
|
|
|
2018-08-10 04:05:47 +08:00
|
|
|
SourceLocation CXXConstructExpr::getEndLoc() const {
|
2012-12-25 22:51:39 +08:00
|
|
|
if (isa<CXXTemporaryObjectExpr>(this))
|
2018-08-10 05:09:38 +08:00
|
|
|
return cast<CXXTemporaryObjectExpr>(this)->getEndLoc();
|
2011-02-21 14:23:05 +08:00
|
|
|
|
2013-09-07 13:49:53 +08:00
|
|
|
if (ParenOrBraceRange.isValid())
|
|
|
|
return ParenOrBraceRange.getEnd();
|
2010-11-03 08:35:38 +08:00
|
|
|
|
2018-12-22 22:39:30 +08:00
|
|
|
SourceLocation End = getLocation();
|
2010-11-03 08:35:38 +08:00
|
|
|
for (unsigned I = getNumArgs(); I > 0; --I) {
|
|
|
|
const Expr *Arg = getArg(I-1);
|
|
|
|
if (!Arg->isDefaultArgument()) {
|
2018-08-10 05:09:38 +08:00
|
|
|
SourceLocation NewEnd = Arg->getEndLoc();
|
2010-11-03 08:35:38 +08:00
|
|
|
if (NewEnd.isValid()) {
|
|
|
|
End = NewEnd;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-25 22:51:39 +08:00
|
|
|
return End;
|
2009-12-23 12:00:48 +08:00
|
|
|
}
|
|
|
|
|
2018-12-21 23:20:32 +08:00
|
|
|
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,
|
2018-12-22 00:51:57 +08:00
|
|
|
OperatorLoc, /*MinNumArgs=*/0, UsesADL) {
|
|
|
|
CXXOperatorCallExprBits.OperatorKind = OpKind;
|
|
|
|
CXXOperatorCallExprBits.FPFeatures = FPFeatures.getInt();
|
2018-12-22 01:54:51 +08:00
|
|
|
assert(
|
|
|
|
(CXXOperatorCallExprBits.OperatorKind == static_cast<unsigned>(OpKind)) &&
|
|
|
|
"OperatorKind overflow!");
|
2018-12-22 00:51:57 +08:00
|
|
|
assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getInt()) &&
|
|
|
|
"FPFeatures overflow!");
|
2018-12-21 23:20:32 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-05-01 06:12:22 +08:00
|
|
|
SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const {
|
2008-11-15 00:09:21 +08:00
|
|
|
OverloadedOperatorKind Kind = getOperator();
|
|
|
|
if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
|
|
|
|
if (getNumArgs() == 1)
|
|
|
|
// Prefix operator
|
2018-08-10 05:09:38 +08:00
|
|
|
return SourceRange(getOperatorLoc(), getArg(0)->getEndLoc());
|
2008-11-15 00:09:21 +08:00
|
|
|
else
|
|
|
|
// Postfix operator
|
2018-08-10 05:08:08 +08:00
|
|
|
return SourceRange(getArg(0)->getBeginLoc(), getOperatorLoc());
|
2011-04-02 17:47:38 +08:00
|
|
|
} else if (Kind == OO_Arrow) {
|
|
|
|
return getArg(0)->getSourceRange();
|
2008-11-15 00:09:21 +08:00
|
|
|
} else if (Kind == OO_Call) {
|
2018-08-10 05:08:08 +08:00
|
|
|
return SourceRange(getArg(0)->getBeginLoc(), getRParenLoc());
|
2008-11-15 00:09:21 +08:00
|
|
|
} else if (Kind == OO_Subscript) {
|
2018-08-10 05:08:08 +08:00
|
|
|
return SourceRange(getArg(0)->getBeginLoc(), getRParenLoc());
|
2008-11-15 00:09:21 +08:00
|
|
|
} else if (getNumArgs() == 1) {
|
2018-08-10 05:09:38 +08:00
|
|
|
return SourceRange(getOperatorLoc(), getArg(0)->getEndLoc());
|
2008-11-15 00:09:21 +08:00
|
|
|
} else if (getNumArgs() == 2) {
|
2018-08-10 05:09:38 +08:00
|
|
|
return SourceRange(getArg(0)->getBeginLoc(), getArg(1)->getEndLoc());
|
2008-11-15 00:09:21 +08:00
|
|
|
} else {
|
2012-05-01 06:12:22 +08:00
|
|
|
return getOperatorLoc();
|
2008-11-15 00:09:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-21 23:20:32 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-03-31 01:41:19 +08:00
|
|
|
Expr *CXXMemberCallExpr::getImplicitObjectArgument() const {
|
2012-08-04 07:08:39 +08:00
|
|
|
const Expr *Callee = getCallee()->IgnoreParens();
|
2018-04-11 06:54:42 +08:00
|
|
|
if (const auto *MemExpr = dyn_cast<MemberExpr>(Callee))
|
2008-12-22 13:46:06 +08:00
|
|
|
return MemExpr->getBase();
|
2018-04-11 06:54:42 +08:00
|
|
|
if (const auto *BO = dyn_cast<BinaryOperator>(Callee))
|
2012-08-04 07:08:39 +08:00
|
|
|
if (BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI)
|
|
|
|
return BO->getLHS();
|
2008-12-22 13:46:06 +08:00
|
|
|
|
|
|
|
// FIXME: Will eventually need to cope with member pointers.
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
2008-12-22 13:46:06 +08:00
|
|
|
}
|
|
|
|
|
2011-03-31 01:41:19 +08:00
|
|
|
CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const {
|
2018-04-11 06:54:42 +08:00
|
|
|
if (const auto *MemExpr = dyn_cast<MemberExpr>(getCallee()->IgnoreParens()))
|
2011-03-31 01:41:19 +08:00
|
|
|
return cast<CXXMethodDecl>(MemExpr->getMemberDecl());
|
|
|
|
|
|
|
|
// FIXME: Will eventually need to cope with member pointers.
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
2011-03-31 01:41:19 +08:00
|
|
|
}
|
|
|
|
|
2012-05-04 00:25:49 +08:00
|
|
|
CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() const {
|
2010-10-27 14:55:41 +08:00
|
|
|
Expr* ThisArg = getImplicitObjectArgument();
|
|
|
|
if (!ThisArg)
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
2010-10-27 14:55:41 +08:00
|
|
|
|
|
|
|
if (ThisArg->getType()->isAnyPointerType())
|
|
|
|
return ThisArg->getType()->getPointeeType()->getAsCXXRecordDecl();
|
|
|
|
|
|
|
|
return ThisArg->getType()->getAsCXXRecordDecl();
|
|
|
|
}
|
|
|
|
|
2008-10-28 03:41:14 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// 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>";
|
|
|
|
}
|
|
|
|
}
|
2009-01-17 02:33:17 +08:00
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T,
|
2010-11-18 14:31:45 +08:00
|
|
|
ExprValueKind VK,
|
2010-08-07 14:22:56 +08:00
|
|
|
CastKind K, Expr *Op,
|
|
|
|
const CXXCastPath *BasePath,
|
|
|
|
TypeSourceInfo *WrittenTy,
|
2018-07-31 03:24:48 +08:00
|
|
|
SourceLocation L,
|
2013-02-23 06:02:53 +08:00
|
|
|
SourceLocation RParenLoc,
|
|
|
|
SourceRange AngleBrackets) {
|
2010-08-07 14:22:56 +08:00
|
|
|
unsigned PathSize = (BasePath ? BasePath->size() : 0);
|
2019-01-10 00:41:33 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2018-04-11 06:54:42 +08:00
|
|
|
auto *E =
|
|
|
|
new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
|
|
|
|
RParenLoc, AngleBrackets);
|
2015-12-30 10:27:28 +08:00
|
|
|
if (PathSize)
|
|
|
|
std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
|
|
|
|
E->getTrailingObjects<CXXBaseSpecifier *>());
|
2010-08-07 14:22:56 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(const ASTContext &C,
|
2010-08-07 14:22:56 +08:00
|
|
|
unsigned PathSize) {
|
2019-01-10 00:41:33 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2010-08-07 14:22:56 +08:00
|
|
|
return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T,
|
2010-11-18 14:31:45 +08:00
|
|
|
ExprValueKind VK,
|
2010-08-07 14:22:56 +08:00
|
|
|
CastKind K, Expr *Op,
|
|
|
|
const CXXCastPath *BasePath,
|
|
|
|
TypeSourceInfo *WrittenTy,
|
2018-07-31 03:24:48 +08:00
|
|
|
SourceLocation L,
|
2013-02-23 06:02:53 +08:00
|
|
|
SourceLocation RParenLoc,
|
|
|
|
SourceRange AngleBrackets) {
|
2010-08-07 14:22:56 +08:00
|
|
|
unsigned PathSize = (BasePath ? BasePath->size() : 0);
|
2019-01-10 00:41:33 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2018-04-11 06:54:42 +08:00
|
|
|
auto *E =
|
|
|
|
new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
|
|
|
|
RParenLoc, AngleBrackets);
|
2015-12-30 10:27:28 +08:00
|
|
|
if (PathSize)
|
|
|
|
std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
|
|
|
|
E->getTrailingObjects<CXXBaseSpecifier *>());
|
2010-08-07 14:22:56 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(const ASTContext &C,
|
2010-08-07 14:22:56 +08:00
|
|
|
unsigned PathSize) {
|
2019-01-10 00:41:33 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2010-08-07 14:22:56 +08:00
|
|
|
return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
|
|
|
|
}
|
|
|
|
|
2011-04-11 09:43:55 +08:00
|
|
|
/// 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();
|
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
if (const auto *SrcPTy = SrcType->getAs<PointerType>()) {
|
2011-04-11 09:43:55 +08:00
|
|
|
SrcType = SrcPTy->getPointeeType();
|
|
|
|
DestType = DestType->castAs<PointerType>()->getPointeeType();
|
|
|
|
}
|
|
|
|
|
2012-06-20 07:44:55 +08:00
|
|
|
if (DestType->isVoidType())
|
|
|
|
return false;
|
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
const auto *SrcRD =
|
|
|
|
cast<CXXRecordDecl>(SrcType->castAs<RecordType>()->getDecl());
|
2011-04-11 09:43:55 +08:00
|
|
|
|
2012-06-20 05:48:43 +08:00
|
|
|
if (!SrcRD->hasAttr<FinalAttr>())
|
|
|
|
return false;
|
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
const auto *DestRD =
|
|
|
|
cast<CXXRecordDecl>(DestType->castAs<RecordType>()->getDecl());
|
2011-04-11 09:43:55 +08:00
|
|
|
|
|
|
|
return !DestRD->isDerivedFrom(SrcRD);
|
|
|
|
}
|
|
|
|
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXReinterpretCastExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T,
|
|
|
|
ExprValueKind VK, CastKind K, Expr *Op,
|
2010-08-07 14:22:56 +08:00
|
|
|
const CXXCastPath *BasePath,
|
2018-07-31 03:24:48 +08:00
|
|
|
TypeSourceInfo *WrittenTy, SourceLocation L,
|
2013-02-23 06:02:53 +08:00
|
|
|
SourceLocation RParenLoc,
|
|
|
|
SourceRange AngleBrackets) {
|
2010-08-07 14:22:56 +08:00
|
|
|
unsigned PathSize = (BasePath ? BasePath->size() : 0);
|
2019-01-10 00:41:33 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2018-04-11 06:54:42 +08:00
|
|
|
auto *E =
|
|
|
|
new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
|
|
|
|
RParenLoc, AngleBrackets);
|
2015-12-30 10:27:28 +08:00
|
|
|
if (PathSize)
|
|
|
|
std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
|
|
|
|
E->getTrailingObjects<CXXBaseSpecifier *>());
|
2010-08-07 14:22:56 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXReinterpretCastExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXReinterpretCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
|
2019-01-10 00:41:33 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2010-08-07 14:22:56 +08:00
|
|
|
return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXConstCastExpr *CXXConstCastExpr::Create(const ASTContext &C, QualType T,
|
2010-11-18 14:31:45 +08:00
|
|
|
ExprValueKind VK, Expr *Op,
|
2010-08-07 14:22:56 +08:00
|
|
|
TypeSourceInfo *WrittenTy,
|
2018-07-31 03:24:48 +08:00
|
|
|
SourceLocation L,
|
2013-02-23 06:02:53 +08:00
|
|
|
SourceLocation RParenLoc,
|
|
|
|
SourceRange AngleBrackets) {
|
|
|
|
return new (C) CXXConstCastExpr(T, VK, Op, WrittenTy, L, RParenLoc, AngleBrackets);
|
2010-08-07 14:22:56 +08:00
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(const ASTContext &C) {
|
2010-08-07 14:22:56 +08:00
|
|
|
return new (C) CXXConstCastExpr(EmptyShell());
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXFunctionalCastExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
|
2013-08-16 06:02:56 +08:00
|
|
|
TypeSourceInfo *Written, CastKind K, Expr *Op,
|
|
|
|
const CXXCastPath *BasePath,
|
|
|
|
SourceLocation L, SourceLocation R) {
|
2010-08-07 14:22:56 +08:00
|
|
|
unsigned PathSize = (BasePath ? BasePath->size() : 0);
|
2019-01-10 00:41:33 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2018-04-11 06:54:42 +08:00
|
|
|
auto *E =
|
|
|
|
new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R);
|
2015-12-30 10:27:28 +08:00
|
|
|
if (PathSize)
|
|
|
|
std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
|
|
|
|
E->getTrailingObjects<CXXBaseSpecifier *>());
|
2010-08-07 14:22:56 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXFunctionalCastExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
|
2019-01-10 00:41:33 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2010-08-07 14:22:56 +08:00
|
|
|
return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
|
|
|
|
}
|
|
|
|
|
2018-08-10 04:05:03 +08:00
|
|
|
SourceLocation CXXFunctionalCastExpr::getBeginLoc() const {
|
2018-08-10 05:08:08 +08:00
|
|
|
return getTypeInfoAsWritten()->getTypeLoc().getBeginLoc();
|
2013-08-16 06:02:56 +08:00
|
|
|
}
|
|
|
|
|
2018-08-10 04:05:47 +08:00
|
|
|
SourceLocation CXXFunctionalCastExpr::getEndLoc() const {
|
2018-08-10 05:09:38 +08:00
|
|
|
return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getEndLoc();
|
2013-08-16 06:02:56 +08:00
|
|
|
}
|
|
|
|
|
2018-12-21 23:20:32 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-03-07 16:35:16 +08:00
|
|
|
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();
|
|
|
|
}
|
2010-08-07 14:22:56 +08:00
|
|
|
|
2018-11-17 21:02:47 +08:00
|
|
|
CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc,
|
Implement __builtin_LINE() et. al. to support source location capture.
Summary:
This patch implements the source location builtins `__builtin_LINE(), `__builtin_FUNCTION()`, `__builtin_FILE()` and `__builtin_COLUMN()`. These builtins are needed to implement [`std::experimental::source_location`](https://rawgit.com/cplusplus/fundamentals-ts/v2/main.html#reflection.src_loc.creation).
With the exception of `__builtin_COLUMN`, GCC also implements these builtins, and Clangs behavior is intended to match as closely as possible.
Reviewers: rsmith, joerg, aaron.ballman, bogner, majnemer, shafik, martong
Reviewed By: rsmith
Subscribers: rnkovacs, loskutov, riccibruno, mgorny, kunitoki, alexr, majnemer, hfinkel, cfe-commits
Differential Revision: https://reviews.llvm.org/D37035
llvm-svn: 360937
2019-05-17 05:04:15 +08:00
|
|
|
FieldDecl *Field, QualType Ty,
|
|
|
|
DeclContext *UsedContext)
|
2018-11-17 21:02:47 +08:00
|
|
|
: Expr(CXXDefaultInitExprClass, Ty.getNonLValueExprType(Ctx),
|
|
|
|
Ty->isLValueReferenceType() ? VK_LValue : Ty->isRValueReferenceType()
|
2013-04-21 06:23:05 +08:00
|
|
|
? VK_XValue
|
|
|
|
: VK_RValue,
|
|
|
|
/*FIXME*/ OK_Ordinary, false, false, false, false),
|
Implement __builtin_LINE() et. al. to support source location capture.
Summary:
This patch implements the source location builtins `__builtin_LINE(), `__builtin_FUNCTION()`, `__builtin_FILE()` and `__builtin_COLUMN()`. These builtins are needed to implement [`std::experimental::source_location`](https://rawgit.com/cplusplus/fundamentals-ts/v2/main.html#reflection.src_loc.creation).
With the exception of `__builtin_COLUMN`, GCC also implements these builtins, and Clangs behavior is intended to match as closely as possible.
Reviewers: rsmith, joerg, aaron.ballman, bogner, majnemer, shafik, martong
Reviewed By: rsmith
Subscribers: rnkovacs, loskutov, riccibruno, mgorny, kunitoki, alexr, majnemer, hfinkel, cfe-commits
Differential Revision: https://reviews.llvm.org/D37035
llvm-svn: 360937
2019-05-17 05:04:15 +08:00
|
|
|
Field(Field), UsedContext(UsedContext) {
|
2018-11-17 21:02:47 +08:00
|
|
|
CXXDefaultInitExprBits.Loc = Loc;
|
2013-04-21 06:23:05 +08:00
|
|
|
assert(Field->hasInClassInitializer());
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXTemporary *CXXTemporary::Create(const ASTContext &C,
|
2009-05-31 04:34:37 +08:00
|
|
|
const CXXDestructorDecl *Destructor) {
|
2009-05-31 06:38:53 +08:00
|
|
|
return new (C) CXXTemporary(Destructor);
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(const ASTContext &C,
|
2009-05-31 04:03:25 +08:00
|
|
|
CXXTemporary *Temp,
|
|
|
|
Expr* SubExpr) {
|
2011-11-28 06:09:28 +08:00
|
|
|
assert((SubExpr->getType()->isRecordType() ||
|
|
|
|
SubExpr->getType()->isArrayType()) &&
|
|
|
|
"Expression bound to a temporary must have record or array type!");
|
2009-05-31 04:03:25 +08:00
|
|
|
|
2010-12-15 09:34:56 +08:00
|
|
|
return new (C) CXXBindTemporaryExpr(Temp, SubExpr);
|
2009-05-31 04:03:25 +08:00
|
|
|
}
|
|
|
|
|
2018-12-22 22:39:30 +08:00
|
|
|
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);
|
|
|
|
}
|
2010-09-08 08:15:04 +08:00
|
|
|
|
2018-08-10 04:05:03 +08:00
|
|
|
SourceLocation CXXTemporaryObjectExpr::getBeginLoc() const {
|
2018-12-22 22:39:30 +08:00
|
|
|
return getTypeSourceInfo()->getTypeLoc().getBeginLoc();
|
2012-12-25 22:51:39 +08:00
|
|
|
}
|
|
|
|
|
2018-08-10 04:05:47 +08:00
|
|
|
SourceLocation CXXTemporaryObjectExpr::getEndLoc() const {
|
2013-09-12 07:23:27 +08:00
|
|
|
SourceLocation Loc = getParenOrBraceRange().getEnd();
|
|
|
|
if (Loc.isInvalid() && getNumArgs())
|
2018-08-10 05:09:38 +08:00
|
|
|
Loc = getArg(getNumArgs() - 1)->getEndLoc();
|
2013-09-12 07:23:27 +08:00
|
|
|
return Loc;
|
2009-01-17 02:33:17 +08:00
|
|
|
}
|
2009-04-21 10:22:11 +08:00
|
|
|
|
2018-12-22 22:39:30 +08:00
|
|
|
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);
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-12-22 22:39:30 +08:00
|
|
|
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];
|
2009-12-17 02:50:27 +08:00
|
|
|
}
|
2009-04-23 10:32:43 +08:00
|
|
|
}
|
|
|
|
|
2018-12-22 22:39:30 +08:00
|
|
|
CXXConstructExpr::CXXConstructExpr(StmtClass SC, EmptyShell Empty,
|
|
|
|
unsigned NumArgs)
|
|
|
|
: Expr(SC, Empty), NumArgs(NumArgs) {}
|
|
|
|
|
2014-05-11 00:31:55 +08:00
|
|
|
LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
|
2012-02-07 18:09:13 +08:00
|
|
|
LambdaCaptureKind Kind, VarDecl *Var,
|
|
|
|
SourceLocation EllipsisLoc)
|
2017-11-18 09:47:41 +08:00
|
|
|
: DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc) {
|
2012-02-07 18:09:13 +08:00
|
|
|
unsigned Bits = 0;
|
|
|
|
if (Implicit)
|
|
|
|
Bits |= Capture_Implicit;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-02-07 18:09:13 +08:00
|
|
|
switch (Kind) {
|
[Cxx1z] Implement Lambda Capture of *this by Value as [=,*this] (P0018R3)
Implement lambda capture of *this by copy.
For e.g.:
struct A {
int d = 10;
auto foo() { return [*this] (auto a) mutable { d+=a; return d; }; }
};
auto L = A{}.foo(); // A{}'s lifetime is gone.
// Below is still ok, because *this was captured by value.
assert(L(10) == 20);
assert(L(100) == 120);
If the capture was implicit, or [this] (i.e. *this was captured by reference), this code would be otherwise undefined.
Implementation Strategy:
- amend the parser to accept *this in the lambda introducer
- add a new king of capture LCK_StarThis
- teach Sema::CheckCXXThisCapture to handle by copy captures of the
enclosing object (i.e. *this)
- when CheckCXXThisCapture does capture by copy, the corresponding
initializer expression for the closure's data member
direct-initializes it thus making a copy of '*this'.
- in codegen, when assigning to CXXThisValue, if *this was captured by
copy, make sure it points to the corresponding field member, and
not, unlike when captured by reference, what the field member points
to.
- mark feature as implemented in svn
Much gratitude to Richard Smith for his carefully illuminating reviews!
llvm-svn: 263921
2016-03-21 17:25:37 +08:00
|
|
|
case LCK_StarThis:
|
|
|
|
Bits |= Capture_ByCopy;
|
2017-12-20 06:06:11 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2014-05-12 13:36:57 +08:00
|
|
|
case LCK_This:
|
|
|
|
assert(!Var && "'this' capture cannot have a variable!");
|
2016-06-15 22:14:51 +08:00
|
|
|
Bits |= Capture_This;
|
2012-02-07 18:09:13 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LCK_ByCopy:
|
|
|
|
Bits |= Capture_ByCopy;
|
2017-12-20 06:06:11 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2012-02-07 18:09:13 +08:00
|
|
|
case LCK_ByRef:
|
|
|
|
assert(Var && "capture must have a variable!");
|
|
|
|
break;
|
2014-08-28 12:28:19 +08:00
|
|
|
case LCK_VLAType:
|
|
|
|
assert(!Var && "VLA type capture cannot have a variable!");
|
|
|
|
break;
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
2016-06-15 22:14:51 +08:00
|
|
|
DeclAndBits.setInt(Bits);
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
|
|
|
|
2014-05-11 00:31:55 +08:00
|
|
|
LambdaCaptureKind LambdaCapture::getCaptureKind() const {
|
2016-06-15 22:14:51 +08:00
|
|
|
if (capturesVLAType())
|
[Cxx1z] Implement Lambda Capture of *this by Value as [=,*this] (P0018R3)
Implement lambda capture of *this by copy.
For e.g.:
struct A {
int d = 10;
auto foo() { return [*this] (auto a) mutable { d+=a; return d; }; }
};
auto L = A{}.foo(); // A{}'s lifetime is gone.
// Below is still ok, because *this was captured by value.
assert(L(10) == 20);
assert(L(100) == 120);
If the capture was implicit, or [this] (i.e. *this was captured by reference), this code would be otherwise undefined.
Implementation Strategy:
- amend the parser to accept *this in the lambda introducer
- add a new king of capture LCK_StarThis
- teach Sema::CheckCXXThisCapture to handle by copy captures of the
enclosing object (i.e. *this)
- when CheckCXXThisCapture does capture by copy, the corresponding
initializer expression for the closure's data member
direct-initializes it thus making a copy of '*this'.
- in codegen, when assigning to CXXThisValue, if *this was captured by
copy, make sure it points to the corresponding field member, and
not, unlike when captured by reference, what the field member points
to.
- mark feature as implemented in svn
Much gratitude to Richard Smith for his carefully illuminating reviews!
llvm-svn: 263921
2016-03-21 17:25:37 +08:00
|
|
|
return LCK_VLAType;
|
2016-06-15 22:14:51 +08:00
|
|
|
bool CapByCopy = DeclAndBits.getInt() & Capture_ByCopy;
|
|
|
|
if (capturesThis())
|
[Cxx1z] Implement Lambda Capture of *this by Value as [=,*this] (P0018R3)
Implement lambda capture of *this by copy.
For e.g.:
struct A {
int d = 10;
auto foo() { return [*this] (auto a) mutable { d+=a; return d; }; }
};
auto L = A{}.foo(); // A{}'s lifetime is gone.
// Below is still ok, because *this was captured by value.
assert(L(10) == 20);
assert(L(100) == 120);
If the capture was implicit, or [this] (i.e. *this was captured by reference), this code would be otherwise undefined.
Implementation Strategy:
- amend the parser to accept *this in the lambda introducer
- add a new king of capture LCK_StarThis
- teach Sema::CheckCXXThisCapture to handle by copy captures of the
enclosing object (i.e. *this)
- when CheckCXXThisCapture does capture by copy, the corresponding
initializer expression for the closure's data member
direct-initializes it thus making a copy of '*this'.
- in codegen, when assigning to CXXThisValue, if *this was captured by
copy, make sure it points to the corresponding field member, and
not, unlike when captured by reference, what the field member points
to.
- mark feature as implemented in svn
Much gratitude to Richard Smith for his carefully illuminating reviews!
llvm-svn: 263921
2016-03-21 17:25:37 +08:00
|
|
|
return CapByCopy ? LCK_StarThis : LCK_This;
|
2014-08-28 12:28:19 +08:00
|
|
|
return CapByCopy ? LCK_ByCopy : LCK_ByRef;
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
|
|
|
|
2015-12-31 12:18:25 +08:00
|
|
|
LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
|
2012-02-07 18:09:13 +08:00
|
|
|
LambdaCaptureDefault CaptureDefault,
|
2013-08-10 07:08:25 +08:00
|
|
|
SourceLocation CaptureDefaultLoc,
|
2015-12-31 12:18:25 +08:00
|
|
|
ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
|
|
|
|
bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
|
2012-07-25 11:56:55 +08:00
|
|
|
SourceLocation ClosingBrace,
|
|
|
|
bool ContainsUnexpandedParameterPack)
|
2015-12-31 12:18:25 +08:00
|
|
|
: 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) {
|
2012-02-07 18:09:13 +08:00
|
|
|
assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
|
2012-02-13 23:44:47 +08:00
|
|
|
CXXRecordDecl *Class = getLambdaClass();
|
|
|
|
CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-02-13 23:44:47 +08:00
|
|
|
// FIXME: Propagate "has unexpanded parameter pack" bit.
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-02-14 01:20:40 +08:00
|
|
|
// Copy captures.
|
2013-08-22 15:09:37 +08:00
|
|
|
const ASTContext &Context = Class->getASTContext();
|
2012-02-14 01:20:40 +08:00
|
|
|
Data.NumCaptures = NumCaptures;
|
|
|
|
Data.NumExplicitCaptures = 0;
|
2015-12-31 12:18:25 +08:00
|
|
|
Data.Captures =
|
|
|
|
(LambdaCapture *)Context.Allocate(sizeof(LambdaCapture) * NumCaptures);
|
|
|
|
LambdaCapture *ToCapture = Data.Captures;
|
2012-02-14 01:20:40 +08:00
|
|
|
for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
|
|
|
|
if (Captures[I].isExplicit())
|
|
|
|
++Data.NumExplicitCaptures;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-02-14 01:20:40 +08:00
|
|
|
*ToCapture++ = Captures[I];
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-02-14 01:20:40 +08:00
|
|
|
// 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];
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-02-14 01:20:40 +08:00
|
|
|
// Copy the body of the lambda.
|
|
|
|
*Stored++ = getCallOperator()->getBody();
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
|
|
|
|
2015-12-31 12:18:25 +08:00
|
|
|
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) {
|
2012-02-07 18:09:13 +08:00
|
|
|
// Determine the type of the expression (i.e., the type of the
|
|
|
|
// function object we're creating).
|
|
|
|
QualType T = Context.getTypeDeclType(Class);
|
|
|
|
|
2016-12-14 08:03:17 +08:00
|
|
|
unsigned Size = totalSizeToAlloc<Stmt *>(Captures.size() + 1);
|
2012-02-14 01:20:40 +08:00
|
|
|
void *Mem = Context.Allocate(Size);
|
2016-12-14 08:03:17 +08:00
|
|
|
return new (Mem)
|
|
|
|
LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc,
|
|
|
|
Captures, ExplicitParams, ExplicitResultType, CaptureInits,
|
|
|
|
ClosingBrace, ContainsUnexpandedParameterPack);
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
|
2016-12-14 08:03:17 +08:00
|
|
|
unsigned NumCaptures) {
|
|
|
|
unsigned Size = totalSizeToAlloc<Stmt *>(NumCaptures + 1);
|
2012-02-15 01:54:36 +08:00
|
|
|
void *Mem = C.Allocate(Size);
|
2016-12-14 08:03:17 +08:00
|
|
|
return new (Mem) LambdaExpr(EmptyShell(), NumCaptures);
|
2012-02-15 01:54:36 +08:00
|
|
|
}
|
|
|
|
|
2015-05-08 02:48:18 +08:00
|
|
|
bool LambdaExpr::isInitCapture(const LambdaCapture *C) const {
|
|
|
|
return (C->capturesVariable() && C->getCapturedVar()->isInitCapture() &&
|
|
|
|
(getCallOperator() == C->getCapturedVar()->getDeclContext()));
|
|
|
|
}
|
|
|
|
|
2012-02-13 23:44:47 +08:00
|
|
|
LambdaExpr::capture_iterator LambdaExpr::capture_begin() const {
|
2012-02-14 01:20:40 +08:00
|
|
|
return getLambdaClass()->getLambdaData().Captures;
|
2012-02-13 23:44:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
LambdaExpr::capture_iterator LambdaExpr::capture_end() const {
|
2012-02-14 01:20:40 +08:00
|
|
|
return capture_begin() + NumCaptures;
|
2012-02-13 23:44:47 +08:00
|
|
|
}
|
|
|
|
|
2014-05-28 03:13:04 +08:00
|
|
|
LambdaExpr::capture_range LambdaExpr::captures() const {
|
|
|
|
return capture_range(capture_begin(), capture_end());
|
|
|
|
}
|
|
|
|
|
2012-02-13 23:44:47 +08:00
|
|
|
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();
|
2012-02-14 01:20:40 +08:00
|
|
|
return Data.Captures + Data.NumExplicitCaptures;
|
2012-02-13 23:44:47 +08:00
|
|
|
}
|
|
|
|
|
2014-05-28 03:13:04 +08:00
|
|
|
LambdaExpr::capture_range LambdaExpr::explicit_captures() const {
|
|
|
|
return capture_range(explicit_capture_begin(), explicit_capture_end());
|
|
|
|
}
|
|
|
|
|
2012-02-13 23:44:47 +08:00
|
|
|
LambdaExpr::capture_iterator LambdaExpr::implicit_capture_begin() const {
|
|
|
|
return explicit_capture_end();
|
|
|
|
}
|
|
|
|
|
|
|
|
LambdaExpr::capture_iterator LambdaExpr::implicit_capture_end() const {
|
|
|
|
return capture_end();
|
|
|
|
}
|
|
|
|
|
2014-05-28 03:13:04 +08:00
|
|
|
LambdaExpr::capture_range LambdaExpr::implicit_captures() const {
|
|
|
|
return capture_range(implicit_capture_begin(), implicit_capture_end());
|
|
|
|
}
|
|
|
|
|
2012-02-07 18:09:13 +08:00
|
|
|
CXXRecordDecl *LambdaExpr::getLambdaClass() const {
|
|
|
|
return getType()->getAsCXXRecordDecl();
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXMethodDecl *LambdaExpr::getCallOperator() const {
|
|
|
|
CXXRecordDecl *Record = getLambdaClass();
|
2018-07-31 03:24:48 +08:00
|
|
|
return Record->getLambdaCallOperator();
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
|
|
|
|
CXXRecordDecl *Record = getLambdaClass();
|
|
|
|
return Record->getGenericLambdaTemplateParameterList();
|
2019-05-04 18:49:46 +08:00
|
|
|
}
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
|
2019-05-04 18:49:46 +08:00
|
|
|
ArrayRef<NamedDecl *> LambdaExpr::getExplicitTemplateParameters() const {
|
|
|
|
const CXXRecordDecl *Record = getLambdaClass();
|
|
|
|
return Record->getLambdaExplicitTemplateParameters();
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
|
|
|
|
2012-02-15 01:54:36 +08:00
|
|
|
CompoundStmt *LambdaExpr::getBody() const {
|
2015-07-18 02:21:37 +08:00
|
|
|
// 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.
|
2012-02-15 01:54:36 +08:00
|
|
|
if (!getStoredStmts()[NumCaptures])
|
2017-11-18 09:47:41 +08:00
|
|
|
*const_cast<Stmt **>(&getStoredStmts()[NumCaptures]) =
|
2015-07-18 02:21:37 +08:00
|
|
|
getCallOperator()->getBody();
|
|
|
|
|
2015-12-31 12:18:25 +08:00
|
|
|
return static_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
|
2012-02-15 01:54:36 +08:00
|
|
|
}
|
|
|
|
|
2012-02-07 18:09:13 +08:00
|
|
|
bool LambdaExpr::isMutable() const {
|
2012-08-10 08:55:35 +08:00
|
|
|
return !getCallOperator()->isConst();
|
2012-02-07 18:09:13 +08:00
|
|
|
}
|
|
|
|
|
2011-11-10 13:35:25 +08:00
|
|
|
ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
|
2016-06-22 04:29:17 +08:00
|
|
|
bool CleanupsHaveSideEffects,
|
2011-11-10 13:35:25 +08:00
|
|
|
ArrayRef<CleanupObject> objects)
|
2018-10-31 11:48:47 +08:00
|
|
|
: FullExpr(ExprWithCleanupsClass, subexpr) {
|
2016-06-22 04:29:17 +08:00
|
|
|
ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects;
|
2011-11-10 13:35:25 +08:00
|
|
|
ExprWithCleanupsBits.NumObjects = objects.size();
|
|
|
|
for (unsigned i = 0, e = objects.size(); i != e; ++i)
|
2015-12-31 12:18:25 +08:00
|
|
|
getTrailingObjects<CleanupObject>()[i] = objects[i];
|
2009-04-25 06:47:04 +08:00
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr,
|
2016-06-22 04:29:17 +08:00
|
|
|
bool CleanupsHaveSideEffects,
|
2011-11-10 13:35:25 +08:00
|
|
|
ArrayRef<CleanupObject> objects) {
|
2015-12-31 12:18:25 +08:00
|
|
|
void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()),
|
2016-10-20 22:27:22 +08:00
|
|
|
alignof(ExprWithCleanups));
|
2016-06-22 04:29:17 +08:00
|
|
|
return new (buffer)
|
|
|
|
ExprWithCleanups(subexpr, CleanupsHaveSideEffects, objects);
|
2010-05-10 08:25:06 +08:00
|
|
|
}
|
|
|
|
|
2011-11-10 13:35:25 +08:00
|
|
|
ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects)
|
2018-10-31 11:48:47 +08:00
|
|
|
: FullExpr(ExprWithCleanupsClass, empty) {
|
2011-11-10 13:35:25 +08:00
|
|
|
ExprWithCleanupsBits.NumObjects = numObjects;
|
|
|
|
}
|
2010-05-10 08:25:06 +08:00
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C,
|
|
|
|
EmptyShell empty,
|
2011-11-10 13:35:25 +08:00
|
|
|
unsigned numObjects) {
|
2015-12-31 12:18:25 +08:00
|
|
|
void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(numObjects),
|
2016-10-20 22:27:22 +08:00
|
|
|
alignof(ExprWithCleanups));
|
2011-11-10 13:35:25 +08:00
|
|
|
return new (buffer) ExprWithCleanups(empty, numObjects);
|
2009-05-31 06:38:53 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 22:27:04 +08:00
|
|
|
CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *TSI,
|
|
|
|
SourceLocation LParenLoc,
|
|
|
|
ArrayRef<Expr *> Args,
|
|
|
|
SourceLocation RParenLoc)
|
2017-11-18 09:47:41 +08:00
|
|
|
: Expr(CXXUnresolvedConstructExprClass,
|
2019-01-07 22:27:04 +08:00
|
|
|
TSI->getType().getNonReferenceType(),
|
|
|
|
(TSI->getType()->isLValueReferenceType()
|
2017-11-18 09:47:41 +08:00
|
|
|
? VK_LValue
|
2019-01-07 22:27:04 +08:00
|
|
|
: TSI->getType()->isRValueReferenceType() ? VK_XValue
|
|
|
|
: VK_RValue),
|
2017-11-18 09:47:41 +08:00
|
|
|
OK_Ordinary,
|
2019-01-07 22:27:04 +08:00
|
|
|
TSI->getType()->isDependentType() ||
|
|
|
|
TSI->getType()->getContainedDeducedType(),
|
|
|
|
true, true, TSI->getType()->containsUnexpandedParameterPack()),
|
|
|
|
TSI(TSI), LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
|
|
|
|
CXXUnresolvedConstructExprBits.NumArgs = Args.size();
|
2018-04-11 06:54:42 +08:00
|
|
|
auto **StoredArgs = getTrailingObjects<Expr *>();
|
2012-08-24 19:54:20 +08:00
|
|
|
for (unsigned I = 0; I != Args.size(); ++I) {
|
2010-12-15 09:34:56 +08:00
|
|
|
if (Args[I]->containsUnexpandedParameterPack())
|
|
|
|
ExprBits.ContainsUnexpandedParameterPack = true;
|
|
|
|
|
|
|
|
StoredArgs[I] = Args[I];
|
|
|
|
}
|
Introduce a new expression type, CXXUnresolvedConstructExpr, to
describe the construction of a value of a given type using function
syntax, e.g.,
T(a1, a2, ..., aN)
when the type or any of its arguments are type-dependent. In this
case, we don't know what kind of type-construction this will be: it
might construct a temporary of type 'T' (which might be a class or
non-class type) or might perform a conversion to type 'T'. Also,
implement printing of and template instantiation for this new
expression type. Due to the change in Sema::ActOnCXXTypeConstructExpr,
our existing tests cover template instantiation of this new expression
node.
llvm-svn: 72176
2009-05-21 02:46:25 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 22:27:04 +08:00
|
|
|
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);
|
Introduce a new expression type, CXXUnresolvedConstructExpr, to
describe the construction of a value of a given type using function
syntax, e.g.,
T(a1, a2, ..., aN)
when the type or any of its arguments are type-dependent. In this
case, we don't know what kind of type-construction this will be: it
might construct a temporary of type 'T' (which might be a class or
non-class type) or might perform a conversion to type 'T'. Also,
implement printing of and template instantiation for this new
expression type. Due to the change in Sema::ActOnCXXTypeConstructExpr,
our existing tests cover template instantiation of this new expression
node.
llvm-svn: 72176
2009-05-21 02:46:25 +08:00
|
|
|
}
|
|
|
|
|
2010-06-24 16:57:31 +08:00
|
|
|
CXXUnresolvedConstructExpr *
|
2019-01-07 22:27:04 +08:00
|
|
|
CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &Context,
|
|
|
|
unsigned NumArgs) {
|
|
|
|
void *Mem = Context.Allocate(totalSizeToAlloc<Expr *>(NumArgs));
|
|
|
|
return new (Mem) CXXUnresolvedConstructExpr(EmptyShell(), NumArgs);
|
2010-06-24 16:57:31 +08:00
|
|
|
}
|
|
|
|
|
2018-08-10 04:05:03 +08:00
|
|
|
SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const {
|
2019-01-07 22:27:04 +08:00
|
|
|
return TSI->getTypeLoc().getBeginLoc();
|
2010-09-08 08:15:04 +08:00
|
|
|
}
|
|
|
|
|
2015-12-30 02:15:14 +08:00
|
|
|
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
|
2019-01-08 22:17:00 +08:00
|
|
|
const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
|
2015-12-30 02:15:14 +08:00
|
|
|
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
|
|
|
|
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
|
|
|
|
DeclarationNameInfo MemberNameInfo,
|
|
|
|
const TemplateArgumentListInfo *TemplateArgs)
|
2019-01-08 22:17:00 +08:00
|
|
|
: Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue,
|
2015-12-30 02:15:14 +08:00
|
|
|
OK_Ordinary, true, true, true,
|
|
|
|
((Base && Base->containsUnexpandedParameterPack()) ||
|
2019-01-08 22:17:00 +08:00
|
|
|
(QualifierLoc && QualifierLoc.getNestedNameSpecifier()
|
|
|
|
->containsUnexpandedParameterPack()) ||
|
2015-12-30 02:15:14 +08:00
|
|
|
MemberNameInfo.containsUnexpandedParameterPack())),
|
2019-01-08 22:17:00 +08:00
|
|
|
Base(Base), BaseType(BaseType), QualifierLoc(QualifierLoc),
|
2015-12-30 02:15:14 +08:00
|
|
|
MemberNameInfo(MemberNameInfo) {
|
2019-01-08 22:17:00 +08:00
|
|
|
CXXDependentScopeMemberExprBits.IsArrow = IsArrow;
|
|
|
|
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
|
|
|
|
(TemplateArgs != nullptr) || TemplateKWLoc.isValid();
|
|
|
|
CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
|
|
|
|
FirstQualifierFoundInScope != nullptr;
|
|
|
|
CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;
|
|
|
|
|
2010-12-15 09:34:56 +08:00
|
|
|
if (TemplateArgs) {
|
|
|
|
bool Dependent = true;
|
2011-07-01 09:22:09 +08:00
|
|
|
bool InstantiationDependent = true;
|
2010-12-15 09:34:56 +08:00
|
|
|
bool ContainsUnexpandedParameterPack = false;
|
2015-12-30 02:15:14 +08:00
|
|
|
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
|
|
|
|
TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
|
|
|
|
Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
|
2010-12-15 09:34:56 +08:00
|
|
|
if (ContainsUnexpandedParameterPack)
|
|
|
|
ExprBits.ContainsUnexpandedParameterPack = true;
|
2012-01-27 17:46:47 +08:00
|
|
|
} else if (TemplateKWLoc.isValid()) {
|
2015-12-30 02:15:14 +08:00
|
|
|
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
|
|
|
|
TemplateKWLoc);
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
2019-01-08 22:17:00 +08:00
|
|
|
|
|
|
|
if (hasFirstQualifierFoundInScope())
|
|
|
|
*getTrailingObjects<NamedDecl *>() = FirstQualifierFoundInScope;
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
|
|
|
|
EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
|
|
|
|
bool HasFirstQualifierFoundInScope)
|
|
|
|
: Expr(CXXDependentScopeMemberExprClass, Empty) {
|
|
|
|
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
|
|
|
|
HasTemplateKWAndArgsInfo;
|
|
|
|
CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
|
|
|
|
HasFirstQualifierFoundInScope;
|
2009-09-09 08:23:06 +08:00
|
|
|
}
|
|
|
|
|
2019-01-08 22:17:00 +08:00
|
|
|
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();
|
2012-01-27 17:46:47 +08:00
|
|
|
unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
|
2019-01-08 22:17:00 +08:00
|
|
|
bool HasFirstQualifierFoundInScope = FirstQualifierFoundInScope != nullptr;
|
2009-11-23 09:53:49 +08:00
|
|
|
|
2019-01-08 22:17:00 +08:00
|
|
|
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);
|
2009-09-09 08:23:06 +08:00
|
|
|
}
|
|
|
|
|
2019-01-08 22:17:00 +08:00
|
|
|
CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::CreateEmpty(
|
|
|
|
const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
|
|
|
|
unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope) {
|
2015-12-30 02:15:14 +08:00
|
|
|
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
|
2010-06-24 16:57:31 +08:00
|
|
|
|
2019-01-08 22:17:00 +08:00
|
|
|
unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
|
|
|
|
TemplateArgumentLoc, NamedDecl *>(
|
|
|
|
HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2019-01-08 22:17:00 +08:00
|
|
|
void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
|
|
|
|
return new (Mem) CXXDependentScopeMemberExpr(
|
|
|
|
EmptyShell(), HasTemplateKWAndArgsInfo, HasFirstQualifierFoundInScope);
|
2011-03-01 04:01:57 +08:00
|
|
|
}
|
|
|
|
|
2011-04-27 04:42:42 +08:00
|
|
|
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.
|
2014-01-22 15:29:52 +08:00
|
|
|
if (cast<CXXMethodDecl>(decl->getUnderlyingDecl()->getAsFunction())
|
|
|
|
->isStatic())
|
2011-04-27 04:42:42 +08:00
|
|
|
return false;
|
|
|
|
} while (++begin != end);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-09 23:43:19 +08:00
|
|
|
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)
|
2017-11-18 09:47:41 +08:00
|
|
|
: OverloadExpr(
|
2019-01-09 23:43:19 +08:00
|
|
|
UnresolvedMemberExprClass, Context, QualifierLoc, TemplateKWLoc,
|
2017-11-18 09:47:41 +08:00
|
|
|
MemberNameInfo, TemplateArgs, Begin, End,
|
|
|
|
// Dependent
|
|
|
|
((Base && Base->isTypeDependent()) || BaseType->isDependentType()),
|
|
|
|
((Base && Base->isInstantiationDependent()) ||
|
|
|
|
BaseType->isInstantiationDependentType()),
|
|
|
|
// Contains unexpanded parameter pack
|
|
|
|
((Base && Base->containsUnexpandedParameterPack()) ||
|
|
|
|
BaseType->containsUnexpandedParameterPack())),
|
2019-01-09 23:43:19 +08:00
|
|
|
Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) {
|
|
|
|
UnresolvedMemberExprBits.IsArrow = IsArrow;
|
|
|
|
UnresolvedMemberExprBits.HasUnresolvedUsing = HasUnresolvedUsing;
|
|
|
|
|
2011-04-27 04:42:42 +08:00
|
|
|
// 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))
|
2019-01-09 23:43:19 +08:00
|
|
|
setType(Context.BoundMemberTy);
|
2009-12-01 06:42:35 +08:00
|
|
|
}
|
|
|
|
|
2019-01-09 23:43:19 +08:00
|
|
|
UnresolvedMemberExpr::UnresolvedMemberExpr(EmptyShell Empty,
|
|
|
|
unsigned NumResults,
|
|
|
|
bool HasTemplateKWAndArgsInfo)
|
|
|
|
: OverloadExpr(UnresolvedMemberExprClass, Empty, NumResults,
|
|
|
|
HasTemplateKWAndArgsInfo) {}
|
|
|
|
|
2011-03-01 04:01:57 +08:00
|
|
|
bool UnresolvedMemberExpr::isImplicitAccess() const {
|
2014-05-12 13:36:57 +08:00
|
|
|
if (!Base)
|
2011-03-01 04:01:57 +08:00
|
|
|
return true;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-03-03 05:06:53 +08:00
|
|
|
return cast<Expr>(Base)->isImplicitCXXThis();
|
2011-03-01 04:01:57 +08:00
|
|
|
}
|
|
|
|
|
2015-12-30 02:15:14 +08:00
|
|
|
UnresolvedMemberExpr *UnresolvedMemberExpr::Create(
|
2019-01-09 23:43:19 +08:00
|
|
|
const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base,
|
|
|
|
QualType BaseType, bool IsArrow, SourceLocation OperatorLoc,
|
2015-12-30 02:15:14 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
|
|
|
|
const DeclarationNameInfo &MemberNameInfo,
|
|
|
|
const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin,
|
|
|
|
UnresolvedSetIterator End) {
|
2019-01-09 23:43:19 +08:00
|
|
|
unsigned NumResults = End - Begin;
|
2015-12-30 02:15:14 +08:00
|
|
|
bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
|
2019-01-09 23:43:19 +08:00
|
|
|
unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
|
|
|
|
unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
|
|
|
|
TemplateArgumentLoc>(
|
|
|
|
NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
|
|
|
|
void *Mem = Context.Allocate(Size, alignof(UnresolvedMemberExpr));
|
2015-12-30 02:15:14 +08:00
|
|
|
return new (Mem) UnresolvedMemberExpr(
|
2019-01-09 23:43:19 +08:00
|
|
|
Context, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc,
|
|
|
|
QualifierLoc, TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End);
|
2009-12-01 06:42:35 +08:00
|
|
|
}
|
|
|
|
|
2019-01-09 23:43:19 +08:00
|
|
|
UnresolvedMemberExpr *UnresolvedMemberExpr::CreateEmpty(
|
|
|
|
const ASTContext &Context, unsigned NumResults,
|
|
|
|
bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) {
|
2015-12-30 02:15:14 +08:00
|
|
|
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
|
2019-01-09 23:43:19 +08:00
|
|
|
unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
|
|
|
|
TemplateArgumentLoc>(
|
|
|
|
NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
|
|
|
|
void *Mem = Context.Allocate(Size, alignof(UnresolvedMemberExpr));
|
|
|
|
return new (Mem)
|
|
|
|
UnresolvedMemberExpr(EmptyShell(), NumResults, HasTemplateKWAndArgsInfo);
|
2010-06-25 17:03:26 +08:00
|
|
|
}
|
|
|
|
|
2019-01-09 23:43:19 +08:00
|
|
|
CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() {
|
2010-01-27 09:50:18 +08:00
|
|
|
// 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.
|
2014-05-12 13:36:57 +08:00
|
|
|
CXXRecordDecl *Record = nullptr;
|
2014-09-26 08:28:20 +08:00
|
|
|
auto *NNS = getQualifier();
|
|
|
|
if (NNS && NNS->getKind() != NestedNameSpecifier::Super) {
|
2011-01-19 14:33:43 +08:00
|
|
|
const Type *T = getQualifier()->getAsType();
|
2010-01-27 09:50:18 +08:00
|
|
|
assert(T && "qualifier in member expression does not name type");
|
2010-04-28 02:19:34 +08:00
|
|
|
Record = T->getAsCXXRecordDecl();
|
|
|
|
assert(Record && "qualifier in member expression does not name record");
|
|
|
|
}
|
2010-01-27 09:50:18 +08:00
|
|
|
// Otherwise the naming class must have been the base class.
|
2010-04-28 02:19:34 +08:00
|
|
|
else {
|
2010-01-27 09:50:18 +08:00
|
|
|
QualType BaseType = getBaseType().getNonReferenceType();
|
|
|
|
if (isArrow()) {
|
2018-04-11 06:54:42 +08:00
|
|
|
const auto *PT = BaseType->getAs<PointerType>();
|
2010-01-27 09:50:18 +08:00
|
|
|
assert(PT && "base of arrow member access is not pointer");
|
|
|
|
BaseType = PT->getPointeeType();
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-04-28 02:19:34 +08:00
|
|
|
Record = BaseType->getAsCXXRecordDecl();
|
|
|
|
assert(Record && "base of member expression does not name record");
|
2010-01-27 09:50:18 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-04-28 02:19:34 +08:00
|
|
|
return Record;
|
2010-01-27 09:50:18 +08:00
|
|
|
}
|
|
|
|
|
2015-09-24 05:41:42 +08:00
|
|
|
SizeOfPackExpr *
|
|
|
|
SizeOfPackExpr::Create(ASTContext &Context, SourceLocation OperatorLoc,
|
|
|
|
NamedDecl *Pack, SourceLocation PackLoc,
|
|
|
|
SourceLocation RParenLoc,
|
|
|
|
Optional<unsigned> Length,
|
|
|
|
ArrayRef<TemplateArgument> PartialArgs) {
|
2015-12-31 12:18:25 +08:00
|
|
|
void *Storage =
|
|
|
|
Context.Allocate(totalSizeToAlloc<TemplateArgument>(PartialArgs.size()));
|
2015-09-24 05:41:42 +08:00
|
|
|
return new (Storage) SizeOfPackExpr(Context.getSizeType(), OperatorLoc, Pack,
|
|
|
|
PackLoc, RParenLoc, Length, PartialArgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
|
|
|
|
unsigned NumPartialArgs) {
|
2015-12-31 12:18:25 +08:00
|
|
|
void *Storage =
|
|
|
|
Context.Allocate(totalSizeToAlloc<TemplateArgument>(NumPartialArgs));
|
2015-09-24 05:41:42 +08:00
|
|
|
return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs);
|
|
|
|
}
|
|
|
|
|
2011-01-15 09:15:58 +08:00
|
|
|
SubstNonTypeTemplateParmPackExpr::
|
2018-07-31 03:24:48 +08:00
|
|
|
SubstNonTypeTemplateParmPackExpr(QualType T,
|
2018-02-14 10:07:53 +08:00
|
|
|
ExprValueKind ValueKind,
|
2011-01-15 09:15:58 +08:00
|
|
|
NonTypeTemplateParmDecl *Param,
|
|
|
|
SourceLocation NameLoc,
|
|
|
|
const TemplateArgument &ArgPack)
|
2018-02-14 10:07:53 +08:00
|
|
|
: Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary,
|
2017-11-18 09:47:41 +08:00
|
|
|
true, true, true, true),
|
|
|
|
Param(Param), Arguments(ArgPack.pack_begin()),
|
|
|
|
NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) {}
|
2011-01-15 09:15:58 +08:00
|
|
|
|
|
|
|
TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
|
2015-08-05 17:40:22 +08:00
|
|
|
return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments));
|
2011-01-15 09:15:58 +08:00
|
|
|
}
|
|
|
|
|
2019-05-22 04:10:50 +08:00
|
|
|
FunctionParmPackExpr::FunctionParmPackExpr(QualType T, VarDecl *ParamPack,
|
2012-09-12 08:56:43 +08:00
|
|
|
SourceLocation NameLoc,
|
|
|
|
unsigned NumParams,
|
2019-05-22 04:10:50 +08:00
|
|
|
VarDecl *const *Params)
|
2015-09-30 22:04:23 +08:00
|
|
|
: Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary, true, true,
|
|
|
|
true, true),
|
|
|
|
ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) {
|
2012-09-12 08:56:43 +08:00
|
|
|
if (Params)
|
|
|
|
std::uninitialized_copy(Params, Params + NumParams,
|
2019-05-22 04:10:50 +08:00
|
|
|
getTrailingObjects<VarDecl *>());
|
2012-09-12 08:56:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FunctionParmPackExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
FunctionParmPackExpr::Create(const ASTContext &Context, QualType T,
|
2019-05-22 04:10:50 +08:00
|
|
|
VarDecl *ParamPack, SourceLocation NameLoc,
|
|
|
|
ArrayRef<VarDecl *> Params) {
|
|
|
|
return new (Context.Allocate(totalSizeToAlloc<VarDecl *>(Params.size())))
|
2015-12-31 12:18:25 +08:00
|
|
|
FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data());
|
2012-09-12 08:56:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FunctionParmPackExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
FunctionParmPackExpr::CreateEmpty(const ASTContext &Context,
|
|
|
|
unsigned NumParams) {
|
2019-05-22 04:10:50 +08:00
|
|
|
return new (Context.Allocate(totalSizeToAlloc<VarDecl *>(NumParams)))
|
2015-12-31 12:18:25 +08:00
|
|
|
FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr);
|
2012-09-12 08:56:43 +08:00
|
|
|
}
|
|
|
|
|
2014-05-02 01:50:17 +08:00
|
|
|
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 *>()) {
|
2018-04-11 06:54:42 +08:00
|
|
|
auto *ES = new (ExtendedBy->getASTContext()) ExtraState;
|
2014-05-02 01:50:17 +08:00
|
|
|
ES->Temporary = State.get<Stmt *>();
|
|
|
|
State = ES;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto ES = State.get<ExtraState *>();
|
|
|
|
ES->ExtendingDecl = ExtendedBy;
|
|
|
|
ES->ManglingNumber = ManglingNumber;
|
|
|
|
}
|
|
|
|
|
2012-02-24 15:38:34 +08:00
|
|
|
TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
|
|
|
|
ArrayRef<TypeSourceInfo *> Args,
|
|
|
|
SourceLocation RParenLoc,
|
|
|
|
bool Value)
|
2017-11-18 09:47:41 +08:00
|
|
|
: Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary,
|
|
|
|
/*TypeDependent=*/false,
|
|
|
|
/*ValueDependent=*/false,
|
|
|
|
/*InstantiationDependent=*/false,
|
|
|
|
/*ContainsUnexpandedParameterPack=*/false),
|
|
|
|
Loc(Loc), RParenLoc(RParenLoc) {
|
2012-02-24 15:38:34 +08:00
|
|
|
TypeTraitExprBits.Kind = Kind;
|
|
|
|
TypeTraitExprBits.Value = Value;
|
|
|
|
TypeTraitExprBits.NumArgs = Args.size();
|
|
|
|
|
2018-04-11 06:54:42 +08:00
|
|
|
auto **ToArgs = getTrailingObjects<TypeSourceInfo *>();
|
2015-12-31 12:18:25 +08:00
|
|
|
|
2012-02-24 15:38:34 +08:00
|
|
|
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);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-02-24 15:38:34 +08:00
|
|
|
ToArgs[I] = Args[I];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
TypeTraitExpr *TypeTraitExpr::Create(const ASTContext &C, QualType T,
|
2018-07-31 03:24:48 +08:00
|
|
|
SourceLocation Loc,
|
2012-02-24 15:38:34 +08:00
|
|
|
TypeTrait Kind,
|
|
|
|
ArrayRef<TypeSourceInfo *> Args,
|
|
|
|
SourceLocation RParenLoc,
|
|
|
|
bool Value) {
|
2015-12-31 12:18:25 +08:00
|
|
|
void *Mem = C.Allocate(totalSizeToAlloc<TypeSourceInfo *>(Args.size()));
|
2012-02-24 15:38:34 +08:00
|
|
|
return new (Mem) TypeTraitExpr(T, Loc, Kind, Args, RParenLoc, Value);
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C,
|
2012-02-24 15:38:34 +08:00
|
|
|
unsigned NumArgs) {
|
2015-12-31 12:18:25 +08:00
|
|
|
void *Mem = C.Allocate(totalSizeToAlloc<TypeSourceInfo *>(NumArgs));
|
2012-02-24 15:38:34 +08:00
|
|
|
return new (Mem) TypeTraitExpr(EmptyShell());
|
|
|
|
}
|
2018-12-21 23:20:32 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|