2007-08-25 04:21:10 +08:00
|
|
|
//===--- ExprCXX.cpp - (C++) Expression AST Node Implementation -----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-08-25 04:21:10 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the subclesses of Expr class declared in 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"
|
2008-11-15 00:09:21 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2009-07-01 06:34:41 +08:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2007-08-25 04:21:10 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2010-02-25 07:40:28 +08:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
2007-08-25 04:21:10 +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
|
2012-12-25 22:51:39 +08:00
|
|
|
SourceLocation CXXScalarValueInitExpr::getLocStart() const {
|
|
|
|
return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : RParenLoc;
|
2010-09-08 08:15:04 +08:00
|
|
|
}
|
|
|
|
|
2008-11-22 03:14:01 +08:00
|
|
|
// CXXNewExpr
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew,
|
|
|
|
FunctionDecl *operatorNew, FunctionDecl *operatorDelete,
|
2016-10-11 02:54:32 +08:00
|
|
|
bool PassAlignment, bool usualArrayDeleteWantsSize,
|
2012-08-24 19:54:20 +08:00
|
|
|
ArrayRef<Expr*> placementArgs,
|
2012-02-16 20:22:20 +08:00
|
|
|
SourceRange typeIdParens, Expr *arraySize,
|
|
|
|
InitializationStyle initializationStyle,
|
|
|
|
Expr *initializer, QualType ty,
|
|
|
|
TypeSourceInfo *allocatedTypeInfo,
|
2012-11-07 08:12:38 +08:00
|
|
|
SourceRange Range, SourceRange directInitRange)
|
2010-11-18 14:31:45 +08:00
|
|
|
: Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary,
|
2010-12-15 09:34:56 +08:00
|
|
|
ty->isDependentType(), ty->isDependentType(),
|
2011-07-01 09:22:09 +08:00
|
|
|
ty->isInstantiationDependentType(),
|
2010-12-15 09:34:56 +08:00
|
|
|
ty->containsUnexpandedParameterPack()),
|
2014-05-12 13:36:57 +08:00
|
|
|
SubExprs(nullptr), OperatorNew(operatorNew), OperatorDelete(operatorDelete),
|
2012-02-16 20:22:20 +08:00
|
|
|
AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens),
|
2012-11-07 08:12:38 +08:00
|
|
|
Range(Range), DirectInitRange(directInitRange),
|
2016-10-11 02:54:32 +08:00
|
|
|
GlobalNew(globalNew), PassAlignment(PassAlignment),
|
|
|
|
UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
|
2014-05-12 13:36:57 +08:00
|
|
|
assert((initializer != nullptr || initializationStyle == NoInit) &&
|
2012-02-16 20:22:20 +08:00
|
|
|
"Only NoInit can have no initializer.");
|
|
|
|
StoredInitializationStyle = initializer ? initializationStyle + 1 : 0;
|
2014-05-12 13:36:57 +08:00
|
|
|
AllocateArgsArray(C, arraySize != nullptr, placementArgs.size(),
|
|
|
|
initializer != nullptr);
|
2008-11-22 03:14:01 +08:00
|
|
|
unsigned i = 0;
|
2010-12-15 09:34:56 +08:00
|
|
|
if (Array) {
|
2011-07-01 09:22:09 +08:00
|
|
|
if (arraySize->isInstantiationDependent())
|
|
|
|
ExprBits.InstantiationDependent = true;
|
|
|
|
|
2010-12-15 09:34:56 +08:00
|
|
|
if (arraySize->containsUnexpandedParameterPack())
|
|
|
|
ExprBits.ContainsUnexpandedParameterPack = true;
|
|
|
|
|
2008-12-02 22:43:59 +08:00
|
|
|
SubExprs[i++] = arraySize;
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
|
|
|
|
2012-02-16 20:22:20 +08:00
|
|
|
if (initializer) {
|
|
|
|
if (initializer->isInstantiationDependent())
|
2011-07-01 09:22:09 +08:00
|
|
|
ExprBits.InstantiationDependent = true;
|
2012-02-16 20:22:20 +08:00
|
|
|
|
|
|
|
if (initializer->containsUnexpandedParameterPack())
|
2010-12-15 09:34:56 +08:00
|
|
|
ExprBits.ContainsUnexpandedParameterPack = true;
|
|
|
|
|
2012-02-16 20:22:20 +08:00
|
|
|
SubExprs[i++] = initializer;
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
|
|
|
|
2012-08-24 19:54:20 +08:00
|
|
|
for (unsigned j = 0; j != placementArgs.size(); ++j) {
|
2012-02-16 20:22:20 +08:00
|
|
|
if (placementArgs[j]->isInstantiationDependent())
|
2011-07-01 09:22:09 +08:00
|
|
|
ExprBits.InstantiationDependent = true;
|
2012-02-16 20:22:20 +08:00
|
|
|
if (placementArgs[j]->containsUnexpandedParameterPack())
|
2010-12-15 09:34:56 +08:00
|
|
|
ExprBits.ContainsUnexpandedParameterPack = true;
|
|
|
|
|
2012-02-16 20:22:20 +08:00
|
|
|
SubExprs[i++] = placementArgs[j];
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
2012-11-09 06:53:48 +08:00
|
|
|
|
|
|
|
switch (getInitializationStyle()) {
|
|
|
|
case CallInit:
|
|
|
|
this->Range.setEnd(DirectInitRange.getEnd()); break;
|
|
|
|
case ListInit:
|
|
|
|
this->Range.setEnd(getInitializer()->getSourceRange().getEnd()); break;
|
2013-06-18 06:35:10 +08:00
|
|
|
default:
|
|
|
|
if (TypeIdParens.isValid())
|
|
|
|
this->Range.setEnd(TypeIdParens.getEnd());
|
|
|
|
break;
|
2012-11-09 06:53:48 +08:00
|
|
|
}
|
2008-11-22 03:14:01 +08:00
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray,
|
2012-02-16 20:22:20 +08:00
|
|
|
unsigned numPlaceArgs, bool hasInitializer){
|
2014-05-12 13:36:57 +08:00
|
|
|
assert(SubExprs == nullptr && "SubExprs already allocated");
|
2010-05-10 09:22:27 +08:00
|
|
|
Array = isArray;
|
|
|
|
NumPlacementArgs = numPlaceArgs;
|
2012-02-16 20:22:20 +08:00
|
|
|
|
|
|
|
unsigned TotalSize = Array + hasInitializer + NumPlacementArgs;
|
2010-05-10 09:22:27 +08:00
|
|
|
SubExprs = new (C) Stmt*[TotalSize];
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const {
|
2015-02-14 09:52:20 +08:00
|
|
|
return getOperatorNew()->getType()->castAs<FunctionProtoType>()->isNothrow(
|
|
|
|
Ctx) &&
|
|
|
|
!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();
|
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)
|
|
|
|
: 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,
|
|
|
|
NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType,
|
|
|
|
SourceLocation ColonColonLoc, SourceLocation TildeLoc,
|
|
|
|
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() ||
|
2011-02-26 02:19:59 +08:00
|
|
|
(QualifierLoc &&
|
|
|
|
QualifierLoc.getNestedNameSpecifier()
|
|
|
|
->containsUnexpandedParameterPack()) ||
|
2010-12-15 09:34:56 +08:00
|
|
|
(ScopeType &&
|
|
|
|
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),
|
|
|
|
DestroyedType(DestroyedType) { }
|
|
|
|
|
2010-02-25 09:56:36 +08:00
|
|
|
QualType CXXPseudoDestructorExpr::getDestroyedType() const {
|
|
|
|
if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
|
|
|
|
return TInfo->getType();
|
|
|
|
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2012-12-25 22:51:39 +08:00
|
|
|
SourceLocation CXXPseudoDestructorExpr::getLocEnd() 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
|
2009-11-25 03:00:30 +08:00
|
|
|
UnresolvedLookupExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
UnresolvedLookupExpr::Create(const ASTContext &C,
|
2010-01-27 09:50:18 +08:00
|
|
|
CXXRecordDecl *NamingClass,
|
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,
|
|
|
|
bool ADL,
|
2012-02-06 22:31:00 +08:00
|
|
|
const TemplateArgumentListInfo *Args,
|
|
|
|
UnresolvedSetIterator Begin,
|
|
|
|
UnresolvedSetIterator End)
|
2009-11-25 03:00:30 +08:00
|
|
|
{
|
2012-02-06 22:31:00 +08:00
|
|
|
assert(Args || TemplateKWLoc.isValid());
|
|
|
|
unsigned num_args = Args ? Args->size() : 0;
|
2015-12-30 02:15:14 +08:00
|
|
|
|
|
|
|
std::size_t Size =
|
|
|
|
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(1,
|
|
|
|
num_args);
|
2016-10-20 22:27:22 +08:00
|
|
|
void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr));
|
2012-01-27 17:46:47 +08:00
|
|
|
return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
|
|
|
|
TemplateKWLoc, NameInfo,
|
2012-02-06 22:31:00 +08:00
|
|
|
ADL, /*Overload*/ true, Args,
|
2012-10-19 01:56:02 +08:00
|
|
|
Begin, End);
|
2009-11-25 03:00:30 +08:00
|
|
|
}
|
|
|
|
|
2010-06-25 17:03:34 +08:00
|
|
|
UnresolvedLookupExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
UnresolvedLookupExpr::CreateEmpty(const ASTContext &C,
|
2012-01-27 17:46:47 +08:00
|
|
|
bool HasTemplateKWAndArgsInfo,
|
2011-02-04 20:01:24 +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);
|
2016-10-20 22:27:22 +08:00
|
|
|
void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr));
|
2010-06-25 17:03:34 +08:00
|
|
|
UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
|
2012-01-27 17:46:47 +08:00
|
|
|
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
|
2010-06-25 17:03:34 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
|
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,
|
2010-05-24 03:36:40 +08:00
|
|
|
UnresolvedSetIterator Begin,
|
2010-12-15 09:34:56 +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)
|
|
|
|
: Expr(K, C.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent,
|
|
|
|
KnownDependent,
|
2011-07-01 09:22:09 +08:00
|
|
|
(KnownInstantiationDependent ||
|
|
|
|
NameInfo.isInstantiationDependent() ||
|
|
|
|
(QualifierLoc &&
|
|
|
|
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
|
2010-12-15 09:34:56 +08:00
|
|
|
(KnownContainsUnexpandedParameterPack ||
|
|
|
|
NameInfo.containsUnexpandedParameterPack() ||
|
2011-03-01 04:01:57 +08:00
|
|
|
(QualifierLoc &&
|
|
|
|
QualifierLoc.getNestedNameSpecifier()
|
|
|
|
->containsUnexpandedParameterPack()))),
|
2012-02-27 04:37:14 +08:00
|
|
|
NameInfo(NameInfo), QualifierLoc(QualifierLoc),
|
2014-05-12 13:36:57 +08:00
|
|
|
Results(nullptr), NumResults(End - Begin),
|
|
|
|
HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
|
|
|
|
TemplateKWLoc.isValid()) {
|
2010-06-25 17:03:26 +08:00
|
|
|
NumResults = End - Begin;
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-20 22:27:22 +08:00
|
|
|
Results = static_cast<DeclAccessPair *>(C.Allocate(
|
|
|
|
sizeof(DeclAccessPair) * NumResults, alignof(DeclAccessPair)));
|
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())
|
|
|
|
setType(C.DependentTy);
|
|
|
|
}
|
2009-11-25 03:00:30 +08:00
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
void OverloadExpr::initializeResults(const ASTContext &C,
|
2010-12-15 09:34:56 +08:00
|
|
|
UnresolvedSetIterator Begin,
|
|
|
|
UnresolvedSetIterator End) {
|
2014-05-12 13:36:57 +08:00
|
|
|
assert(!Results && "Results already initialized!");
|
2010-12-15 09:34:56 +08:00
|
|
|
NumResults = End - Begin;
|
|
|
|
if (NumResults) {
|
2016-10-20 22:27:22 +08:00
|
|
|
Results = static_cast<DeclAccessPair *>(
|
|
|
|
C.Allocate(sizeof(DeclAccessPair) * NumResults,
|
|
|
|
|
|
|
|
alignof(DeclAccessPair)));
|
|
|
|
memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
|
2010-12-15 09:34:56 +08:00
|
|
|
}
|
2009-11-25 03:00:30 +08:00
|
|
|
}
|
|
|
|
|
2010-04-23 02:44:12 +08:00
|
|
|
CXXRecordDecl *OverloadExpr::getNamingClass() const {
|
|
|
|
if (isa<UnresolvedLookupExpr>(this))
|
|
|
|
return cast<UnresolvedLookupExpr>(this)->getNamingClass();
|
|
|
|
else
|
|
|
|
return cast<UnresolvedMemberExpr>(this)->getNamingClass();
|
|
|
|
}
|
|
|
|
|
2009-11-20 06:55:06 +08:00
|
|
|
// DependentScopeDeclRefExpr
|
2010-12-15 09:34:56 +08:00
|
|
|
DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
|
2011-02-26 04:49:16 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2012-01-27 17:46:47 +08:00
|
|
|
SourceLocation TemplateKWLoc,
|
2010-12-15 09:34:56 +08:00
|
|
|
const DeclarationNameInfo &NameInfo,
|
|
|
|
const TemplateArgumentListInfo *Args)
|
|
|
|
: Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary,
|
|
|
|
true, true,
|
2011-07-01 09:22:09 +08:00
|
|
|
(NameInfo.isInstantiationDependent() ||
|
|
|
|
(QualifierLoc &&
|
|
|
|
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())),
|
2010-12-15 09:34:56 +08:00
|
|
|
(NameInfo.containsUnexpandedParameterPack() ||
|
2011-02-26 04:49:16 +08:00
|
|
|
(QualifierLoc &&
|
|
|
|
QualifierLoc.getNestedNameSpecifier()
|
|
|
|
->containsUnexpandedParameterPack()))),
|
|
|
|
QualifierLoc(QualifierLoc), NameInfo(NameInfo),
|
2014-05-12 13:36:57 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-25 03:00:30 +08:00
|
|
|
DependentScopeDeclRefExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
DependentScopeDeclRefExpr::Create(const ASTContext &C,
|
2011-02-26 04:49:16 +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,
|
2009-11-25 03:00:30 +08:00
|
|
|
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);
|
|
|
|
void *Mem = C.Allocate(Size);
|
2012-01-27 17:46:47 +08:00
|
|
|
return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc,
|
|
|
|
TemplateKWLoc, NameInfo, Args);
|
2009-11-25 03:00:30 +08:00
|
|
|
}
|
|
|
|
|
2010-06-28 17:31:56 +08:00
|
|
|
DependentScopeDeclRefExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &C,
|
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);
|
|
|
|
void *Mem = C.Allocate(Size);
|
2012-01-27 17:46:47 +08:00
|
|
|
DependentScopeDeclRefExpr *E
|
2011-02-26 04:49:16 +08:00
|
|
|
= new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(),
|
2012-01-27 17:46:47 +08:00
|
|
|
SourceLocation(),
|
2014-05-12 13:36:57 +08:00
|
|
|
DeclarationNameInfo(), nullptr);
|
2012-01-27 17:46:47 +08:00
|
|
|
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
|
2011-02-04 20:01:24 +08:00
|
|
|
return E;
|
2010-06-28 17:31:56 +08:00
|
|
|
}
|
|
|
|
|
2012-12-25 22:51:39 +08:00
|
|
|
SourceLocation CXXConstructExpr::getLocStart() const {
|
2011-02-21 14:23:05 +08:00
|
|
|
if (isa<CXXTemporaryObjectExpr>(this))
|
2012-12-25 22:51:39 +08:00
|
|
|
return cast<CXXTemporaryObjectExpr>(this)->getLocStart();
|
|
|
|
return Loc;
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation CXXConstructExpr::getLocEnd() const {
|
|
|
|
if (isa<CXXTemporaryObjectExpr>(this))
|
|
|
|
return cast<CXXTemporaryObjectExpr>(this)->getLocEnd();
|
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
|
|
|
|
|
|
|
SourceLocation End = Loc;
|
|
|
|
for (unsigned I = getNumArgs(); I > 0; --I) {
|
|
|
|
const Expr *Arg = getArg(I-1);
|
|
|
|
if (!Arg->isDefaultArgument()) {
|
|
|
|
SourceLocation NewEnd = Arg->getLocEnd();
|
|
|
|
if (NewEnd.isValid()) {
|
|
|
|
End = NewEnd;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-25 22:51:39 +08:00
|
|
|
return End;
|
2009-12-23 12:00:48 +08:00
|
|
|
}
|
|
|
|
|
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
|
2012-05-02 06:19:11 +08:00
|
|
|
return SourceRange(getOperatorLoc(), getArg(0)->getLocEnd());
|
2008-11-15 00:09:21 +08:00
|
|
|
else
|
|
|
|
// Postfix operator
|
2012-05-02 06:19:11 +08:00
|
|
|
return SourceRange(getArg(0)->getLocStart(), 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) {
|
2012-05-02 06:19:11 +08:00
|
|
|
return SourceRange(getArg(0)->getLocStart(), getRParenLoc());
|
2008-11-15 00:09:21 +08:00
|
|
|
} else if (Kind == OO_Subscript) {
|
2012-05-02 06:19:11 +08:00
|
|
|
return SourceRange(getArg(0)->getLocStart(), getRParenLoc());
|
2008-11-15 00:09:21 +08:00
|
|
|
} else if (getNumArgs() == 1) {
|
2012-05-02 06:19:11 +08:00
|
|
|
return SourceRange(getOperatorLoc(), getArg(0)->getLocEnd());
|
2008-11-15 00:09:21 +08:00
|
|
|
} else if (getNumArgs() == 2) {
|
2012-05-02 06:19:11 +08:00
|
|
|
return SourceRange(getArg(0)->getLocStart(), getArg(1)->getLocEnd());
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
if (const MemberExpr *MemExpr = dyn_cast<MemberExpr>(Callee))
|
2008-12-22 13:46:06 +08:00
|
|
|
return MemExpr->getBase();
|
2012-08-04 07:08:39 +08:00
|
|
|
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(Callee))
|
|
|
|
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 {
|
|
|
|
if (const MemberExpr *MemExpr =
|
|
|
|
dyn_cast<MemberExpr>(getCallee()->IgnoreParens()))
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2009-11-12 23:31:47 +08:00
|
|
|
|
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,
|
2011-01-13 06:41:29 +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);
|
2015-12-30 10:27:28 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXStaticCastExpr *E =
|
2011-01-13 06:41:29 +08:00
|
|
|
new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
|
2013-02-23 06:02:53 +08:00
|
|
|
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) {
|
2015-12-30 10:27:28 +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,
|
2011-01-13 06:41:29 +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);
|
2015-12-30 10:27:28 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXDynamicCastExpr *E =
|
2011-01-13 06:41:29 +08:00
|
|
|
new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
|
2013-02-23 06:02:53 +08:00
|
|
|
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) {
|
2015-12-30 10:27:28 +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();
|
|
|
|
|
|
|
|
if (const PointerType *SrcPTy = SrcType->getAs<PointerType>()) {
|
|
|
|
SrcType = SrcPTy->getPointeeType();
|
|
|
|
DestType = DestType->castAs<PointerType>()->getPointeeType();
|
|
|
|
}
|
|
|
|
|
2012-06-20 07:44:55 +08:00
|
|
|
if (DestType->isVoidType())
|
|
|
|
return false;
|
|
|
|
|
2011-04-11 09:43:55 +08:00
|
|
|
const CXXRecordDecl *SrcRD =
|
|
|
|
cast<CXXRecordDecl>(SrcType->castAs<RecordType>()->getDecl());
|
|
|
|
|
2012-06-20 05:48:43 +08:00
|
|
|
if (!SrcRD->hasAttr<FinalAttr>())
|
|
|
|
return false;
|
|
|
|
|
2011-04-11 09:43:55 +08:00
|
|
|
const CXXRecordDecl *DestRD =
|
|
|
|
cast<CXXRecordDecl>(DestType->castAs<RecordType>()->getDecl());
|
|
|
|
|
|
|
|
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,
|
2011-01-13 06:41:29 +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);
|
2015-12-30 10:27:28 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXReinterpretCastExpr *E =
|
2011-01-13 06:41:29 +08:00
|
|
|
new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
|
2013-02-23 06:02:53 +08:00
|
|
|
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) {
|
2015-12-30 10:27:28 +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,
|
2011-01-13 06:41:29 +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);
|
2015-12-30 10:27:28 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXFunctionalCastExpr *E =
|
2013-08-16 06:02:56 +08:00
|
|
|
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) {
|
2015-12-30 10:27:28 +08:00
|
|
|
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
|
2010-08-07 14:22:56 +08:00
|
|
|
return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
|
|
|
|
}
|
|
|
|
|
2013-08-16 06:02:56 +08:00
|
|
|
SourceLocation CXXFunctionalCastExpr::getLocStart() const {
|
|
|
|
return getTypeInfoAsWritten()->getTypeLoc().getLocStart();
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation CXXFunctionalCastExpr::getLocEnd() const {
|
|
|
|
return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getLocEnd();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc,
|
2013-04-21 06:23:05 +08:00
|
|
|
FieldDecl *Field, QualType T)
|
|
|
|
: Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C),
|
|
|
|
T->isLValueReferenceType() ? VK_LValue : T->isRValueReferenceType()
|
|
|
|
? VK_XValue
|
|
|
|
: VK_RValue,
|
|
|
|
/*FIXME*/ OK_Ordinary, false, false, false, false),
|
|
|
|
Field(Field), Loc(Loc) {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C,
|
2009-04-24 13:23:13 +08:00
|
|
|
CXXConstructorDecl *Cons,
|
2017-02-10 03:17:44 +08:00
|
|
|
QualType Type,
|
|
|
|
TypeSourceInfo *TSI,
|
2012-08-24 19:54:20 +08:00
|
|
|
ArrayRef<Expr*> Args,
|
2013-09-07 13:49:53 +08:00
|
|
|
SourceRange ParenOrBraceRange,
|
2011-10-05 15:56:41 +08:00
|
|
|
bool HadMultipleCandidates,
|
2012-12-19 09:39:02 +08:00
|
|
|
bool ListInitialization,
|
2014-07-17 13:12:35 +08:00
|
|
|
bool StdInitListInitialization,
|
2010-04-28 04:36:09 +08:00
|
|
|
bool ZeroInitialization)
|
2017-02-10 03:17:44 +08:00
|
|
|
: CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type,
|
|
|
|
TSI->getTypeLoc().getBeginLoc(),
|
2016-06-10 08:58:19 +08:00
|
|
|
Cons, false, Args,
|
2012-12-19 09:39:02 +08:00
|
|
|
HadMultipleCandidates,
|
2014-07-17 13:12:35 +08:00
|
|
|
ListInitialization,
|
|
|
|
StdInitListInitialization,
|
|
|
|
ZeroInitialization,
|
2013-09-07 13:49:53 +08:00
|
|
|
CXXConstructExpr::CK_Complete, ParenOrBraceRange),
|
2017-02-10 03:17:44 +08:00
|
|
|
Type(TSI) {
|
2010-09-08 08:15:04 +08:00
|
|
|
}
|
|
|
|
|
2012-12-25 22:51:39 +08:00
|
|
|
SourceLocation CXXTemporaryObjectExpr::getLocStart() const {
|
|
|
|
return Type->getTypeLoc().getBeginLoc();
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation CXXTemporaryObjectExpr::getLocEnd() const {
|
2013-09-12 07:23:27 +08:00
|
|
|
SourceLocation Loc = getParenOrBraceRange().getEnd();
|
|
|
|
if (Loc.isInvalid() && getNumArgs())
|
|
|
|
Loc = getArg(getNumArgs()-1)->getLocEnd();
|
|
|
|
return Loc;
|
2009-01-17 02:33:17 +08:00
|
|
|
}
|
2009-04-21 10:22:11 +08:00
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T,
|
2009-12-16 09:38:02 +08:00
|
|
|
SourceLocation Loc,
|
2016-05-12 04:37:46 +08:00
|
|
|
CXXConstructorDecl *Ctor,
|
|
|
|
bool Elidable,
|
2012-08-24 19:54:20 +08:00
|
|
|
ArrayRef<Expr*> Args,
|
2011-10-05 15:56:41 +08:00
|
|
|
bool HadMultipleCandidates,
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
bool ListInitialization,
|
2014-07-17 13:12:35 +08:00
|
|
|
bool StdInitListInitialization,
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
bool ZeroInitialization,
|
2010-10-25 16:47:36 +08:00
|
|
|
ConstructionKind ConstructKind,
|
2013-09-07 13:49:53 +08:00
|
|
|
SourceRange ParenOrBraceRange) {
|
2016-05-12 04:37:46 +08:00
|
|
|
return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc,
|
2016-06-10 08:58:19 +08:00
|
|
|
Ctor, Elidable, Args,
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
HadMultipleCandidates, ListInitialization,
|
2014-07-17 13:12:35 +08:00
|
|
|
StdInitListInitialization,
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
ZeroInitialization, ConstructKind,
|
2013-09-07 13:49:53 +08:00
|
|
|
ParenOrBraceRange);
|
2009-04-23 10:32:43 +08:00
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC,
|
|
|
|
QualType T, SourceLocation Loc,
|
2016-06-10 08:58:19 +08:00
|
|
|
CXXConstructorDecl *Ctor,
|
2016-05-12 04:37:46 +08:00
|
|
|
bool Elidable,
|
|
|
|
ArrayRef<Expr*> Args,
|
2011-10-05 15:56:41 +08:00
|
|
|
bool HadMultipleCandidates,
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
bool ListInitialization,
|
2014-07-17 13:12:35 +08:00
|
|
|
bool StdInitListInitialization,
|
2011-10-05 15:56:41 +08:00
|
|
|
bool ZeroInitialization,
|
2010-10-25 16:47:36 +08:00
|
|
|
ConstructionKind ConstructKind,
|
2013-09-07 13:49:53 +08:00
|
|
|
SourceRange ParenOrBraceRange)
|
2010-12-15 09:34:56 +08:00
|
|
|
: Expr(SC, T, VK_RValue, OK_Ordinary,
|
|
|
|
T->isDependentType(), T->isDependentType(),
|
2011-07-01 09:22:09 +08:00
|
|
|
T->isInstantiationDependentType(),
|
2010-12-15 09:34:56 +08:00
|
|
|
T->containsUnexpandedParameterPack()),
|
2016-05-12 04:37:46 +08:00
|
|
|
Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange),
|
|
|
|
NumArgs(Args.size()),
|
|
|
|
Elidable(Elidable), HadMultipleCandidates(HadMultipleCandidates),
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
ListInitialization(ListInitialization),
|
2014-07-17 13:12:35 +08:00
|
|
|
StdInitListInitialization(StdInitListInitialization),
|
2011-10-05 15:56:41 +08:00
|
|
|
ZeroInitialization(ZeroInitialization),
|
2014-05-12 13:36:57 +08:00
|
|
|
ConstructKind(ConstructKind), Args(nullptr)
|
2009-12-17 02:50:27 +08:00
|
|
|
{
|
|
|
|
if (NumArgs) {
|
2016-05-12 04:37:46 +08:00
|
|
|
this->Args = new (C) Stmt*[Args.size()];
|
2009-12-17 02:50:27 +08:00
|
|
|
|
2016-05-12 04:37:46 +08:00
|
|
|
for (unsigned i = 0; i != Args.size(); ++i) {
|
|
|
|
assert(Args[i] && "NULL argument in CXXConstructExpr");
|
2010-12-15 09:34:56 +08:00
|
|
|
|
2016-05-12 04:37:46 +08:00
|
|
|
if (Args[i]->isValueDependent())
|
2010-12-15 09:34:56 +08:00
|
|
|
ExprBits.ValueDependent = true;
|
2016-05-12 04:37:46 +08:00
|
|
|
if (Args[i]->isInstantiationDependent())
|
2011-07-01 09:22:09 +08:00
|
|
|
ExprBits.InstantiationDependent = true;
|
2016-05-12 04:37:46 +08:00
|
|
|
if (Args[i]->containsUnexpandedParameterPack())
|
2010-12-15 09:34:56 +08:00
|
|
|
ExprBits.ContainsUnexpandedParameterPack = true;
|
|
|
|
|
2016-05-12 04:37:46 +08:00
|
|
|
this->Args[i] = Args[i];
|
2009-04-23 10:32:43 +08:00
|
|
|
}
|
2009-12-17 02:50:27 +08:00
|
|
|
}
|
2009-04-23 10:32:43 +08:00
|
|
|
}
|
|
|
|
|
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)
|
2016-06-15 22:14:51 +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;
|
|
|
|
|
|
|
|
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;
|
|
|
|
// Fall through
|
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;
|
|
|
|
// Fall through
|
|
|
|
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();
|
|
|
|
|
|
|
|
// FIXME: Propagate "has unexpanded parameter pack" bit.
|
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;
|
|
|
|
|
|
|
|
*ToCapture++ = Captures[I];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy initialization expressions for the non-static data members.
|
|
|
|
Stmt **Stored = getStoredStmts();
|
|
|
|
for (unsigned I = 0, N = CaptureInits.size(); I != N; ++I)
|
|
|
|
*Stored++ = CaptureInits[I];
|
|
|
|
|
|
|
|
// Copy the body of the lambda.
|
|
|
|
*Stored++ = getCallOperator()->getBody();
|
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();
|
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
|
|
|
return Record->getLambdaCallOperator();
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
|
|
|
|
CXXRecordDecl *Record = getLambdaClass();
|
|
|
|
return Record->getGenericLambdaTemplateParameterList();
|
|
|
|
|
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])
|
2015-07-18 02:21:37 +08:00
|
|
|
*const_cast<clang::Stmt **>(&getStoredStmts()[NumCaptures]) =
|
|
|
|
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)
|
2010-12-06 16:20:24 +08:00
|
|
|
: Expr(ExprWithCleanupsClass, subexpr->getType(),
|
2010-11-18 14:31:45 +08:00
|
|
|
subexpr->getValueKind(), subexpr->getObjectKind(),
|
2010-12-15 09:34:56 +08:00
|
|
|
subexpr->isTypeDependent(), subexpr->isValueDependent(),
|
2011-07-01 09:22:09 +08:00
|
|
|
subexpr->isInstantiationDependent(),
|
2010-12-15 09:34:56 +08:00
|
|
|
subexpr->containsUnexpandedParameterPack()),
|
2011-11-10 13:35:25 +08:00
|
|
|
SubExpr(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)
|
|
|
|
: Expr(ExprWithCleanupsClass, empty) {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2010-09-08 08:15:04 +08:00
|
|
|
CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
|
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
|
|
|
SourceLocation LParenLoc,
|
2012-08-24 19:54:20 +08:00
|
|
|
ArrayRef<Expr*> Args,
|
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
|
|
|
SourceLocation RParenLoc)
|
2010-09-08 08:15:04 +08:00
|
|
|
: Expr(CXXUnresolvedConstructExprClass,
|
|
|
|
Type->getType().getNonReferenceType(),
|
2011-07-08 23:50:43 +08:00
|
|
|
(Type->getType()->isLValueReferenceType() ? VK_LValue
|
|
|
|
:Type->getType()->isRValueReferenceType()? VK_XValue
|
|
|
|
:VK_RValue),
|
|
|
|
OK_Ordinary,
|
2017-08-11 10:04:19 +08:00
|
|
|
Type->getType()->isDependentType() ||
|
|
|
|
Type->getType()->getContainedDeducedType(),
|
|
|
|
true, true,
|
2010-12-15 09:34:56 +08:00
|
|
|
Type->getType()->containsUnexpandedParameterPack()),
|
2010-09-08 08:15:04 +08:00
|
|
|
Type(Type),
|
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
|
|
|
LParenLoc(LParenLoc),
|
|
|
|
RParenLoc(RParenLoc),
|
2012-08-24 19:54:20 +08:00
|
|
|
NumArgs(Args.size()) {
|
2015-12-31 12:18:25 +08:00
|
|
|
Expr **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
|
|
|
}
|
|
|
|
|
|
|
|
CXXUnresolvedConstructExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXUnresolvedConstructExpr::Create(const ASTContext &C,
|
2010-09-08 08:15:04 +08:00
|
|
|
TypeSourceInfo *Type,
|
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
|
|
|
SourceLocation LParenLoc,
|
2012-08-24 19:54:20 +08:00
|
|
|
ArrayRef<Expr*> Args,
|
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
|
|
|
SourceLocation RParenLoc) {
|
2015-12-31 12:18:25 +08:00
|
|
|
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Args.size()));
|
2012-08-24 19:54:20 +08:00
|
|
|
return new (Mem) CXXUnresolvedConstructExpr(Type, 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 *
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &C, unsigned NumArgs) {
|
2010-06-24 16:57:31 +08:00
|
|
|
Stmt::EmptyShell Empty;
|
2015-12-31 12:18:25 +08:00
|
|
|
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumArgs));
|
2010-06-24 16:57:31 +08:00
|
|
|
return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs);
|
|
|
|
}
|
|
|
|
|
2012-12-25 22:51:39 +08:00
|
|
|
SourceLocation CXXUnresolvedConstructExpr::getLocStart() const {
|
|
|
|
return Type->getTypeLoc().getBeginLoc();
|
2010-09-08 08:15:04 +08:00
|
|
|
}
|
|
|
|
|
2015-12-30 02:15:14 +08:00
|
|
|
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
|
|
|
|
const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow,
|
|
|
|
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
|
|
|
|
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
|
|
|
|
DeclarationNameInfo MemberNameInfo,
|
|
|
|
const TemplateArgumentListInfo *TemplateArgs)
|
|
|
|
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy, VK_LValue,
|
|
|
|
OK_Ordinary, true, true, true,
|
|
|
|
((Base && Base->containsUnexpandedParameterPack()) ||
|
|
|
|
(QualifierLoc &&
|
|
|
|
QualifierLoc.getNestedNameSpecifier()
|
|
|
|
->containsUnexpandedParameterPack()) ||
|
|
|
|
MemberNameInfo.containsUnexpandedParameterPack())),
|
|
|
|
Base(Base), BaseType(BaseType), IsArrow(IsArrow),
|
|
|
|
HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
|
|
|
|
TemplateKWLoc.isValid()),
|
|
|
|
OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
|
|
|
|
FirstQualifierFoundInScope(FirstQualifierFoundInScope),
|
|
|
|
MemberNameInfo(MemberNameInfo) {
|
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
|
|
|
}
|
2009-09-09 08:23:06 +08:00
|
|
|
}
|
|
|
|
|
2009-11-20 06:55:06 +08:00
|
|
|
CXXDependentScopeMemberExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXDependentScopeMemberExpr::Create(const ASTContext &C,
|
2009-12-02 06:10:20 +08:00
|
|
|
Expr *Base, QualType BaseType, bool IsArrow,
|
2009-09-09 08:23:06 +08:00
|
|
|
SourceLocation OperatorLoc,
|
2011-03-01 02:50:33 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2012-01-27 17:46:47 +08:00
|
|
|
SourceLocation TemplateKWLoc,
|
2009-09-09 08:23:06 +08:00
|
|
|
NamedDecl *FirstQualifierFoundInScope,
|
2010-08-12 06:01:17 +08:00
|
|
|
DeclarationNameInfo MemberNameInfo,
|
2009-11-23 09:53:49 +08:00
|
|
|
const TemplateArgumentListInfo *TemplateArgs) {
|
2015-12-30 02:15:14 +08:00
|
|
|
bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
|
2012-01-27 17:46:47 +08:00
|
|
|
unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
|
2015-12-30 02:15:14 +08:00
|
|
|
std::size_t Size =
|
|
|
|
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
|
|
|
|
HasTemplateKWAndArgsInfo, NumTemplateArgs);
|
2009-11-23 09:53:49 +08:00
|
|
|
|
2016-10-20 22:27:22 +08:00
|
|
|
void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
|
2009-12-02 06:10:20 +08:00
|
|
|
return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType,
|
|
|
|
IsArrow, OperatorLoc,
|
2011-03-01 02:50:33 +08:00
|
|
|
QualifierLoc,
|
2012-01-27 17:46:47 +08:00
|
|
|
TemplateKWLoc,
|
2009-12-02 06:10:20 +08:00
|
|
|
FirstQualifierFoundInScope,
|
2010-08-12 06:01:17 +08:00
|
|
|
MemberNameInfo, TemplateArgs);
|
2009-09-09 08:23:06 +08:00
|
|
|
}
|
|
|
|
|
2010-06-24 16:57:31 +08:00
|
|
|
CXXDependentScopeMemberExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C,
|
2012-01-27 17:46:47 +08:00
|
|
|
bool HasTemplateKWAndArgsInfo,
|
2010-06-24 16:57:31 +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);
|
2016-10-20 22:27:22 +08:00
|
|
|
void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
|
2010-06-24 16:57:31 +08:00
|
|
|
CXXDependentScopeMemberExpr *E
|
2014-05-12 13:36:57 +08:00
|
|
|
= new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
|
2012-01-27 17:46:47 +08:00
|
|
|
0, SourceLocation(),
|
|
|
|
NestedNameSpecifierLoc(),
|
2014-05-12 13:36:57 +08:00
|
|
|
SourceLocation(), nullptr,
|
|
|
|
DeclarationNameInfo(), nullptr);
|
2015-12-30 02:15:14 +08:00
|
|
|
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
|
2010-06-24 16:57:31 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2011-03-01 04:01:57 +08:00
|
|
|
bool CXXDependentScopeMemberExpr::isImplicitAccess() const {
|
2014-05-12 13:36:57 +08:00
|
|
|
if (!Base)
|
2011-03-01 04:01:57 +08:00
|
|
|
return true;
|
|
|
|
|
2011-03-03 05:06:53 +08:00
|
|
|
return cast<Expr>(Base)->isImplicitCXXThis();
|
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;
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C,
|
2009-12-01 06:42:35 +08:00
|
|
|
bool HasUnresolvedUsing,
|
2009-12-02 06:10:20 +08:00
|
|
|
Expr *Base, QualType BaseType,
|
|
|
|
bool IsArrow,
|
2009-12-01 06:42:35 +08:00
|
|
|
SourceLocation OperatorLoc,
|
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 &MemberNameInfo,
|
2010-05-24 02:57:34 +08:00
|
|
|
const TemplateArgumentListInfo *TemplateArgs,
|
|
|
|
UnresolvedSetIterator Begin,
|
|
|
|
UnresolvedSetIterator End)
|
2012-01-27 17:46:47 +08:00
|
|
|
: OverloadExpr(UnresolvedMemberExprClass, C, QualifierLoc, TemplateKWLoc,
|
|
|
|
MemberNameInfo, TemplateArgs, Begin, End,
|
2010-12-15 09:34:56 +08:00
|
|
|
// Dependent
|
|
|
|
((Base && Base->isTypeDependent()) ||
|
|
|
|
BaseType->isDependentType()),
|
2011-07-01 09:22:09 +08:00
|
|
|
((Base && Base->isInstantiationDependent()) ||
|
|
|
|
BaseType->isInstantiationDependentType()),
|
2010-12-15 09:34:56 +08:00
|
|
|
// Contains unexpanded parameter pack
|
|
|
|
((Base && Base->containsUnexpandedParameterPack()) ||
|
|
|
|
BaseType->containsUnexpandedParameterPack())),
|
2010-02-02 14:20:04 +08:00
|
|
|
IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing),
|
|
|
|
Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) {
|
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))
|
|
|
|
setType(C.BoundMemberTy);
|
2009-12-01 06:42:35 +08:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
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(
|
|
|
|
const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType,
|
|
|
|
bool IsArrow, SourceLocation OperatorLoc,
|
|
|
|
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
|
|
|
|
const DeclarationNameInfo &MemberNameInfo,
|
|
|
|
const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin,
|
|
|
|
UnresolvedSetIterator End) {
|
|
|
|
bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
|
|
|
|
std::size_t Size =
|
|
|
|
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
|
|
|
|
HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0);
|
|
|
|
|
2016-10-20 22:27:22 +08:00
|
|
|
void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr));
|
2015-12-30 02:15:14 +08:00
|
|
|
return new (Mem) UnresolvedMemberExpr(
|
|
|
|
C, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc,
|
|
|
|
TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End);
|
2009-12-01 06:42:35 +08:00
|
|
|
}
|
|
|
|
|
2010-06-25 17:03:26 +08:00
|
|
|
UnresolvedMemberExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
UnresolvedMemberExpr::CreateEmpty(const ASTContext &C,
|
|
|
|
bool HasTemplateKWAndArgsInfo,
|
2011-02-04 20:01:24 +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);
|
2010-06-25 17:03:26 +08:00
|
|
|
|
2016-10-20 22:27:22 +08:00
|
|
|
void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr));
|
2010-06-25 17:03:26 +08:00
|
|
|
UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
|
2012-01-27 17:46:47 +08:00
|
|
|
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
|
2010-06-25 17:03:26 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2010-01-27 09:50:18 +08:00
|
|
|
CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
|
|
|
|
// 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()) {
|
|
|
|
const PointerType *PT = BaseType->getAs<PointerType>();
|
|
|
|
assert(PT && "base of arrow member access is not pointer");
|
|
|
|
BaseType = PT->getPointeeType();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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::
|
|
|
|
SubstNonTypeTemplateParmPackExpr(QualType T,
|
|
|
|
NonTypeTemplateParmDecl *Param,
|
|
|
|
SourceLocation NameLoc,
|
|
|
|
const TemplateArgument &ArgPack)
|
|
|
|
: Expr(SubstNonTypeTemplateParmPackExprClass, T, VK_RValue, OK_Ordinary,
|
2011-07-01 09:22:09 +08:00
|
|
|
true, true, true, true),
|
2011-01-15 09:15:58 +08:00
|
|
|
Param(Param), Arguments(ArgPack.pack_begin()),
|
|
|
|
NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { }
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-09-12 08:56:43 +08:00
|
|
|
FunctionParmPackExpr::FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
|
|
|
|
SourceLocation NameLoc,
|
|
|
|
unsigned NumParams,
|
2015-09-30 22:04:23 +08:00
|
|
|
ParmVarDecl *const *Params)
|
|
|
|
: 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,
|
2015-12-31 12:18:25 +08:00
|
|
|
getTrailingObjects<ParmVarDecl *>());
|
2012-09-12 08:56:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FunctionParmPackExpr *
|
2013-08-22 15:09:37 +08:00
|
|
|
FunctionParmPackExpr::Create(const ASTContext &Context, QualType T,
|
2012-09-12 08:56:43 +08:00
|
|
|
ParmVarDecl *ParamPack, SourceLocation NameLoc,
|
2015-09-30 22:04:23 +08:00
|
|
|
ArrayRef<ParmVarDecl *> Params) {
|
2015-12-31 12:18:25 +08:00
|
|
|
return new (Context.Allocate(totalSizeToAlloc<ParmVarDecl *>(Params.size())))
|
|
|
|
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) {
|
2015-12-31 12:18:25 +08:00
|
|
|
return new (Context.Allocate(totalSizeToAlloc<ParmVarDecl *>(NumParams)))
|
|
|
|
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 *>()) {
|
|
|
|
auto ES = new (ExtendedBy->getASTContext()) ExtraState;
|
|
|
|
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)
|
|
|
|
: Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary,
|
|
|
|
/*TypeDependent=*/false,
|
|
|
|
/*ValueDependent=*/false,
|
|
|
|
/*InstantiationDependent=*/false,
|
|
|
|
/*ContainsUnexpandedParameterPack=*/false),
|
|
|
|
Loc(Loc), RParenLoc(RParenLoc)
|
|
|
|
{
|
|
|
|
TypeTraitExprBits.Kind = Kind;
|
|
|
|
TypeTraitExprBits.Value = Value;
|
|
|
|
TypeTraitExprBits.NumArgs = Args.size();
|
|
|
|
|
2015-12-31 12:18:25 +08:00
|
|
|
TypeSourceInfo **ToArgs = getTrailingObjects<TypeSourceInfo *>();
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
ToArgs[I] = Args[I];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-22 15:09:37 +08:00
|
|
|
TypeTraitExpr *TypeTraitExpr::Create(const ASTContext &C, QualType T,
|
2012-02-24 15:38:34 +08:00
|
|
|
SourceLocation Loc,
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void ArrayTypeTraitExpr::anchor() { }
|