aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/TreeTransform.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/TreeTransform.h')
-rw-r--r--lib/Sema/TreeTransform.h733
1 files changed, 548 insertions, 185 deletions
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index df14768cbe81..8df18b5c2784 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1,9 +1,8 @@
//===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//===----------------------------------------------------------------------===//
//
// This file implements a semantic tree transformation that takes a given
@@ -149,6 +148,11 @@ public:
/// statement node appears at most once in its containing declaration.
bool AlwaysRebuild() { return SemaRef.ArgumentPackSubstitutionIndex != -1; }
+ /// Whether the transformation is forming an expression or statement that
+ /// replaces the original. In this case, we'll reuse mangling numbers from
+ /// existing lambdas.
+ bool ReplacingOriginal() { return false; }
+
/// Returns the location of the entity being transformed, if that
/// information was not available elsewhere in the AST.
///
@@ -319,6 +323,13 @@ public:
TypeSourceInfo *TransformTypeWithDeducedTST(TypeSourceInfo *DI);
/// @}
+ /// The reason why the value of a statement is not discarded, if any.
+ enum StmtDiscardKind {
+ SDK_Discarded,
+ SDK_NotDiscarded,
+ SDK_StmtExprResult,
+ };
+
/// Transform the given statement.
///
/// By default, this routine transforms a statement by delegating to the
@@ -328,7 +339,7 @@ public:
/// other mechanism.
///
/// \returns the transformed statement.
- StmtResult TransformStmt(Stmt *S, bool DiscardedValue = false);
+ StmtResult TransformStmt(Stmt *S, StmtDiscardKind SDK = SDK_Discarded);
/// Transform the given statement.
///
@@ -444,8 +455,10 @@ public:
/// TransformDefinition. However, in some cases (e.g., lambda expressions),
/// the transformer itself has to transform the declarations. This routine
/// can be overridden by a subclass that keeps track of such mappings.
- void transformedLocalDecl(Decl *Old, Decl *New) {
- TransformedLocalDecls[Old] = New;
+ void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> New) {
+ assert(New.size() == 1 &&
+ "must override transformedLocalDecl if performing pack expansion");
+ TransformedLocalDecls[Old] = New.front();
}
/// Transform the definition of the given declaration.
@@ -646,6 +659,12 @@ public:
Optional<unsigned> NumExpansions,
bool ExpectParameterPack);
+ /// Transform the body of a lambda-expression.
+ StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body);
+ /// Alternative implementation of TransformLambdaBody that skips transforming
+ /// the body.
+ StmtResult SkipLambdaBody(LambdaExpr *E, Stmt *Body);
+
QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
@@ -673,6 +692,9 @@ public:
#define STMT(Node, Parent) \
LLVM_ATTRIBUTE_NOINLINE \
StmtResult Transform##Node(Node *S);
+#define VALUESTMT(Node, Parent) \
+ LLVM_ATTRIBUTE_NOINLINE \
+ StmtResult Transform##Node(Node *S, StmtDiscardKind SDK);
#define EXPR(Node, Parent) \
LLVM_ATTRIBUTE_NOINLINE \
ExprResult Transform##Node(Node *E);
@@ -874,6 +896,12 @@ public:
return SemaRef.Context.getTypeDeclType(Typedef);
}
+ /// Build a new MacroDefined type.
+ QualType RebuildMacroQualifiedType(QualType T,
+ const IdentifierInfo *MacroII) {
+ return SemaRef.Context.getMacroQualifiedType(T, MacroII);
+ }
+
/// Build a new class/struct/union type.
QualType RebuildRecordType(RecordDecl *Record) {
return SemaRef.Context.getTypeDeclType(Record);
@@ -1356,10 +1384,11 @@ public:
unsigned NumInputs, IdentifierInfo **Names,
MultiExprArg Constraints, MultiExprArg Exprs,
Expr *AsmString, MultiExprArg Clobbers,
+ unsigned NumLabels,
SourceLocation RParenLoc) {
return getSema().ActOnGCCAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs,
NumInputs, Names, Constraints, Exprs,
- AsmString, Clobbers, RParenLoc);
+ AsmString, Clobbers, NumLabels, RParenLoc);
}
/// Build a new MS style inline asm statement.
@@ -1545,6 +1574,16 @@ public:
return getSema().ActOnOpenMPSimdlenClause(Len, StartLoc, LParenLoc, EndLoc);
}
+ /// Build a new OpenMP 'allocator' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPAllocatorClause(Expr *A, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPAllocatorClause(A, StartLoc, LParenLoc, EndLoc);
+ }
+
/// Build a new OpenMP 'collapse' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@@ -1795,17 +1834,30 @@ public:
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
- OMPClause *
- RebuildOMPMapClause(ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
- ArrayRef<SourceLocation> MapTypeModifiersLoc,
- OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
- SourceLocation MapLoc, SourceLocation ColonLoc,
- ArrayRef<Expr *> VarList, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc) {
+ OMPClause *RebuildOMPMapClause(
+ ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
+ ArrayRef<SourceLocation> MapTypeModifiersLoc,
+ CXXScopeSpec MapperIdScopeSpec, DeclarationNameInfo MapperId,
+ OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
+ SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
return getSema().ActOnOpenMPMapClause(MapTypeModifiers, MapTypeModifiersLoc,
- MapType, IsMapTypeImplicit, MapLoc,
- ColonLoc, VarList, StartLoc,
- LParenLoc, EndLoc);
+ MapperIdScopeSpec, MapperId, MapType,
+ IsMapTypeImplicit, MapLoc, ColonLoc,
+ VarList, Locs, UnresolvedMappers);
+ }
+
+ /// Build a new OpenMP 'allocate' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPAllocateClause(Expr *Allocate, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPAllocateClause(Allocate, VarList, StartLoc,
+ LParenLoc, ColonLoc, EndLoc);
}
/// Build a new OpenMP 'num_teams' clause.
@@ -1892,10 +1944,12 @@ public:
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPToClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc) {
- return getSema().ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc);
+ CXXScopeSpec &MapperIdScopeSpec,
+ DeclarationNameInfo &MapperId,
+ const OMPVarListLocTy &Locs,
+ ArrayRef<Expr *> UnresolvedMappers) {
+ return getSema().ActOnOpenMPToClause(VarList, MapperIdScopeSpec, MapperId,
+ Locs, UnresolvedMappers);
}
/// Build a new OpenMP 'from' clause.
@@ -1903,11 +1957,12 @@ public:
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPFromClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc) {
- return getSema().ActOnOpenMPFromClause(VarList, StartLoc, LParenLoc,
- EndLoc);
+ CXXScopeSpec &MapperIdScopeSpec,
+ DeclarationNameInfo &MapperId,
+ const OMPVarListLocTy &Locs,
+ ArrayRef<Expr *> UnresolvedMappers) {
+ return getSema().ActOnOpenMPFromClause(VarList, MapperIdScopeSpec, MapperId,
+ Locs, UnresolvedMappers);
}
/// Build a new OpenMP 'use_device_ptr' clause.
@@ -1915,11 +1970,8 @@ public:
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc) {
- return getSema().ActOnOpenMPUseDevicePtrClause(VarList, StartLoc, LParenLoc,
- EndLoc);
+ const OMPVarListLocTy &Locs) {
+ return getSema().ActOnOpenMPUseDevicePtrClause(VarList, Locs);
}
/// Build a new OpenMP 'is_device_ptr' clause.
@@ -1927,11 +1979,8 @@ public:
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc) {
- return getSema().ActOnOpenMPIsDevicePtrClause(VarList, StartLoc, LParenLoc,
- EndLoc);
+ const OMPVarListLocTy &Locs) {
+ return getSema().ActOnOpenMPIsDevicePtrClause(VarList, Locs);
}
/// Rebuild the operand to an Objective-C \@synchronized statement.
@@ -2232,8 +2281,8 @@ public:
MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig = nullptr) {
- return getSema().ActOnCallExpr(/*Scope=*/nullptr, Callee, LParenLoc,
- Args, RParenLoc, ExecConfig);
+ return getSema().BuildCallExpr(/*Scope=*/nullptr, Callee, LParenLoc, Args,
+ RParenLoc, ExecConfig);
}
/// Build a new member access expression.
@@ -2603,6 +2652,16 @@ public:
ListInitialization);
}
+ /// Build a new C++ __builtin_bit_cast expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildBuiltinBitCastExpr(SourceLocation KWLoc,
+ TypeSourceInfo *TSI, Expr *Sub,
+ SourceLocation RParenLoc) {
+ return getSema().BuildBuiltinBitCastExpr(KWLoc, TSI, Sub, RParenLoc);
+ }
+
/// Build a new C++ typeid(type) expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -2660,8 +2719,7 @@ public:
ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
QualType ThisType,
bool isImplicit) {
- getSema().CheckCXXThisCapture(ThisLoc);
- return new (getSema().Context) CXXThisExpr(ThisLoc, ThisType, isImplicit);
+ return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit);
}
/// Build a new C++ throw expression.
@@ -2678,9 +2736,9 @@ public:
/// By default, builds a new default-argument expression, which does not
/// require any semantic analysis. Subclasses may override this routine to
/// provide different behavior.
- ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc,
- ParmVarDecl *Param) {
- return CXXDefaultArgExpr::Create(getSema().Context, Loc, Param);
+ ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, ParmVarDecl *Param) {
+ return CXXDefaultArgExpr::Create(getSema().Context, Loc, Param,
+ getSema().CurContext);
}
/// Build a new C++11 default-initialization expression.
@@ -2690,7 +2748,8 @@ public:
/// routine to provide different behavior.
ExprResult RebuildCXXDefaultInitExpr(SourceLocation Loc,
FieldDecl *Field) {
- return CXXDefaultInitExpr::Create(getSema().Context, Loc, Field);
+ return CXXDefaultInitExpr::Create(getSema().Context, Loc, Field,
+ getSema().CurContext);
}
/// Build a new C++ zero-initialization expression.
@@ -2716,7 +2775,7 @@ public:
SourceRange TypeIdParens,
QualType AllocatedType,
TypeSourceInfo *AllocatedTypeInfo,
- Expr *ArraySize,
+ Optional<Expr *> ArraySize,
SourceRange DirectInitRange,
Expr *Initializer) {
return getSema().BuildCXXNew(StartLoc, UseGlobal,
@@ -2944,6 +3003,18 @@ public:
RParenLoc, Length, PartialArgs);
}
+ /// Build a new expression representing a call to a source location
+ /// builtin.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildSourceLocExpr(SourceLocExpr::IdentKind Kind,
+ SourceLocation BuiltinLoc,
+ SourceLocation RPLoc,
+ DeclContext *ParentContext) {
+ return getSema().BuildSourceLocExpr(Kind, BuiltinLoc, RPLoc, ParentContext);
+ }
+
/// Build a new Objective-C boxed expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -3219,9 +3290,10 @@ public:
ExprResult RebuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
BinaryOperatorKind Operator,
SourceLocation EllipsisLoc, Expr *RHS,
- SourceLocation RParenLoc) {
+ SourceLocation RParenLoc,
+ Optional<unsigned> NumExpansions) {
return getSema().BuildCXXFoldExpr(LParenLoc, LHS, Operator, EllipsisLoc,
- RHS, RParenLoc);
+ RHS, RParenLoc, NumExpansions);
}
/// Build an empty C++1z fold-expression with the given operator.
@@ -3270,7 +3342,7 @@ private:
};
template <typename Derived>
-StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) {
+StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, StmtDiscardKind SDK) {
if (!S)
return S;
@@ -3278,8 +3350,12 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) {
case Stmt::NoStmtClass: break;
// Transform individual statement nodes
+ // Pass SDK into statements that can produce a value
#define STMT(Node, Parent) \
case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(S));
+#define VALUESTMT(Node, Parent) \
+ case Stmt::Node##Class: \
+ return getDerived().Transform##Node(cast<Node>(S), SDK);
#define ABSTRACT_STMT(Node)
#define EXPR(Node, Parent)
#include "clang/AST/StmtNodes.inc"
@@ -3291,10 +3367,10 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) {
#include "clang/AST/StmtNodes.inc"
{
ExprResult E = getDerived().TransformExpr(cast<Expr>(S));
- if (E.isInvalid())
- return StmtError();
- return getSema().ActOnExprStmt(E, DiscardedValue);
+ if (SDK == SDK_StmtExprResult)
+ E = getSema().ActOnStmtExprResult(E);
+ return getSema().ActOnExprStmt(E, SDK == SDK_Discarded);
}
}
@@ -3879,10 +3955,6 @@ template<typename Derived>
bool TreeTransform<Derived>::TransformTemplateArgument(
const TemplateArgumentLoc &Input,
TemplateArgumentLoc &Output, bool Uneval) {
- EnterExpressionEvaluationContext EEEC(
- SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated,
- /*LambdaContextDecl=*/nullptr, /*ExprContext=*/
- Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument);
const TemplateArgument &Arg = Input.getArgument();
switch (Arg.getKind()) {
case TemplateArgument::Null:
@@ -3931,9 +4003,11 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
case TemplateArgument::Expression: {
// Template argument expressions are constant expressions.
EnterExpressionEvaluationContext Unevaluated(
- getSema(), Uneval
- ? Sema::ExpressionEvaluationContext::Unevaluated
- : Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ getSema(),
+ Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
+ : Sema::ExpressionEvaluationContext::ConstantEvaluated,
+ /*LambdaContextDecl=*/nullptr, /*ExprContext=*/
+ Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument);
Expr *InputExpr = Input.getSourceExpression();
if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
@@ -4462,6 +4536,14 @@ QualType TreeTransform<Derived>::TransformDecayedType(TypeLocBuilder &TLB,
return Result;
}
+/// Helper to deduce addr space of a pointee type in OpenCL mode.
+/// If the type is updated it will be overwritten in PointeeType param.
+static void deduceOpenCLPointeeAddrSpace(Sema &SemaRef, QualType &PointeeType) {
+ if (PointeeType.getAddressSpace() == LangAS::Default)
+ PointeeType = SemaRef.Context.getAddrSpaceQualType(PointeeType,
+ LangAS::opencl_generic);
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
PointerTypeLoc TL) {
@@ -4470,6 +4552,9 @@ QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
if (PointeeType.isNull())
return QualType();
+ if (SemaRef.getLangOpts().OpenCL)
+ deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType);
+
QualType Result = TL.getType();
if (PointeeType->getAs<ObjCObjectType>()) {
// A dependent pointer type 'T *' has is being transformed such
@@ -4508,6 +4593,9 @@ TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
if (PointeeType.isNull())
return QualType();
+ if (SemaRef.getLangOpts().OpenCL)
+ deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType);
+
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
PointeeType != TL.getPointeeLoc().getType()) {
@@ -4537,6 +4625,9 @@ TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB,
if (PointeeType.isNull())
return QualType();
+ if (SemaRef.getLangOpts().OpenCL)
+ deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType);
+
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
PointeeType != T->getPointeeTypeAsWritten()) {
@@ -5301,13 +5392,6 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType(
if (ResultType.isNull())
return QualType();
- // Return type can not be qualified with an address space.
- if (ResultType.getAddressSpace() != LangAS::Default) {
- SemaRef.Diag(TL.getReturnLoc().getBeginLoc(),
- diag::err_attribute_address_function_type);
- return QualType();
- }
-
if (getDerived().TransformFunctionTypeParams(
TL.getBeginLoc(), TL.getParams(),
TL.getTypePtr()->param_type_begin(),
@@ -6160,6 +6244,27 @@ TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB,
return Result;
}
+template <typename Derived>
+QualType
+TreeTransform<Derived>::TransformMacroQualifiedType(TypeLocBuilder &TLB,
+ MacroQualifiedTypeLoc TL) {
+ QualType Inner = getDerived().TransformType(TLB, TL.getInnerLoc());
+ if (Inner.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || Inner != TL.getInnerLoc().getType()) {
+ Result =
+ getDerived().RebuildMacroQualifiedType(Inner, TL.getMacroIdentifier());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ MacroQualifiedTypeLoc NewTL = TLB.push<MacroQualifiedTypeLoc>(Result);
+ NewTL.setExpansionLoc(TL.getExpansionLoc());
+ return Result;
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformDependentNameType(
TypeLocBuilder &TLB, DependentNameTypeLoc TL) {
@@ -6517,12 +6622,13 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
bool IsStmtExpr) {
Sema::CompoundScopeRAII CompoundScope(getSema());
+ const Stmt *ExprResult = S->getStmtExprResult();
bool SubStmtInvalid = false;
bool SubStmtChanged = false;
SmallVector<Stmt*, 8> Statements;
for (auto *B : S->body()) {
- StmtResult Result =
- getDerived().TransformStmt(B, !IsStmtExpr || B != S->body_back());
+ StmtResult Result = getDerived().TransformStmt(
+ B, IsStmtExpr && B == ExprResult ? SDK_StmtExprResult : SDK_Discarded);
if (Result.isInvalid()) {
// Immediately fail if this was a DeclStmt, since it's very
@@ -6585,7 +6691,8 @@ TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) {
return StmtError();
// Transform the statement following the case
- StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ StmtResult SubStmt =
+ getDerived().TransformStmt(S->getSubStmt());
if (SubStmt.isInvalid())
return StmtError();
@@ -6593,11 +6700,11 @@ TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) {
return getDerived().RebuildCaseStmtBody(Case.get(), SubStmt.get());
}
-template<typename Derived>
-StmtResult
-TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) {
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) {
// Transform the statement following the default case
- StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ StmtResult SubStmt =
+ getDerived().TransformStmt(S->getSubStmt());
if (SubStmt.isInvalid())
return StmtError();
@@ -6608,8 +6715,8 @@ TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) {
template<typename Derived>
StmtResult
-TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
- StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S, StmtDiscardKind SDK) {
+ StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK);
if (SubStmt.isInvalid())
return StmtError();
@@ -6618,6 +6725,11 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
if (!LD)
return StmtError();
+ // If we're transforming "in-place" (we're not creating new local
+ // declarations), assume we're replacing the old label statement
+ // and clear out the reference to it.
+ if (LD == S->getDecl())
+ S->getDecl()->setStmt(nullptr);
// FIXME: Pass the real colon location in.
return getDerived().RebuildLabelStmt(S->getIdentLoc(),
@@ -6643,7 +6755,9 @@ const Attr *TreeTransform<Derived>::TransformAttr(const Attr *R) {
}
template <typename Derived>
-StmtResult TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) {
+StmtResult
+TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S,
+ StmtDiscardKind SDK) {
bool AttrsChanged = false;
SmallVector<const Attr *, 1> Attrs;
@@ -6654,7 +6768,7 @@ StmtResult TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) {
Attrs.push_back(R);
}
- StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK);
if (SubStmt.isInvalid())
return StmtError();
@@ -6967,6 +7081,16 @@ TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) {
Exprs.push_back(Result.get());
}
+ // Go through the Labels.
+ for (unsigned I = 0, E = S->getNumLabels(); I != E; ++I) {
+ Names.push_back(S->getLabelIdentifier(I));
+
+ ExprResult Result = getDerived().TransformExpr(S->getLabelExpr(I));
+ if (Result.isInvalid())
+ return StmtError();
+ ExprsChanged |= Result.get() != S->getLabelExpr(I);
+ Exprs.push_back(Result.get());
+ }
if (!getDerived().AlwaysRebuild() && !ExprsChanged)
return S;
@@ -6980,7 +7104,8 @@ TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) {
S->isVolatile(), S->getNumOutputs(),
S->getNumInputs(), Names.data(),
Constraints, Exprs, AsmString.get(),
- Clobbers, S->getRParenLoc());
+ Clobbers, S->getNumLabels(),
+ S->getRParenLoc());
}
template<typename Derived>
@@ -7039,7 +7164,7 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
auto *Promise = SemaRef.buildCoroutinePromise(FD->getLocation());
if (!Promise)
return StmtError();
- getDerived().transformedLocalDecl(S->getPromiseDecl(), Promise);
+ getDerived().transformedLocalDecl(S->getPromiseDecl(), {Promise});
ScopeInfo->CoroutinePromise = Promise;
// Transform the implicit coroutine statements we built during the initial
@@ -7071,13 +7196,22 @@ TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
Builder.ReturnValue = Res.get();
if (S->hasDependentPromiseType()) {
- assert(!Promise->getType()->isDependentType() &&
- "the promise type must no longer be dependent");
- assert(!S->getFallthroughHandler() && !S->getExceptionHandler() &&
- !S->getReturnStmtOnAllocFailure() && !S->getDeallocate() &&
- "these nodes should not have been built yet");
- if (!Builder.buildDependentStatements())
- return StmtError();
+ // PR41909: We may find a generic coroutine lambda definition within a
+ // template function that is being instantiated. In this case, the lambda
+ // will have a dependent promise type, until it is used in an expression
+ // that creates an instantiation with a non-dependent promise type. We
+ // should not assert or build coroutine dependent statements for such a
+ // generic lambda.
+ auto *MD = dyn_cast_or_null<CXXMethodDecl>(FD);
+ if (!MD || !MD->getParent()->isGenericLambda()) {
+ assert(!Promise->getType()->isDependentType() &&
+ "the promise type must no longer be dependent");
+ assert(!S->getFallthroughHandler() && !S->getExceptionHandler() &&
+ !S->getReturnStmtOnAllocFailure() && !S->getDeallocate() &&
+ "these nodes should not have been built yet");
+ if (!Builder.buildDependentStatements())
+ return StmtError();
+ }
} else {
if (auto *OnFallthrough = S->getFallthroughHandler()) {
StmtResult Res = getDerived().TransformStmt(OnFallthrough);
@@ -7359,7 +7493,8 @@ StmtResult
TreeTransform<Derived>::TransformObjCForCollectionStmt(
ObjCForCollectionStmt *S) {
// Transform the element statement.
- StmtResult Element = getDerived().TransformStmt(S->getElement());
+ StmtResult Element =
+ getDerived().TransformStmt(S->getElement(), SDK_NotDiscarded);
if (Element.isInvalid())
return StmtError();
@@ -8325,6 +8460,16 @@ TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) {
template <typename Derived>
OMPClause *
+TreeTransform<Derived>::TransformOMPAllocatorClause(OMPAllocatorClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getAllocator());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPAllocatorClause(
+ E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+}
+
+template <typename Derived>
+OMPClause *
TreeTransform<Derived>::TransformOMPSimdlenClause(OMPSimdlenClause *C) {
ExprResult E = getDerived().TransformExpr(C->getSimdlen());
if (E.isInvalid())
@@ -8797,8 +8942,85 @@ TreeTransform<Derived>::TransformOMPDeviceClause(OMPDeviceClause *C) {
C->getLParenLoc(), C->getEndLoc());
}
+template <typename Derived, class T>
+bool transformOMPMappableExprListClause(
+ TreeTransform<Derived> &TT, OMPMappableExprListClause<T> *C,
+ llvm::SmallVectorImpl<Expr *> &Vars, CXXScopeSpec &MapperIdScopeSpec,
+ DeclarationNameInfo &MapperIdInfo,
+ llvm::SmallVectorImpl<Expr *> &UnresolvedMappers) {
+ // Transform expressions in the list.
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = TT.getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return true;
+ Vars.push_back(EVar.get());
+ }
+ // Transform mapper scope specifier and identifier.
+ NestedNameSpecifierLoc QualifierLoc;
+ if (C->getMapperQualifierLoc()) {
+ QualifierLoc = TT.getDerived().TransformNestedNameSpecifierLoc(
+ C->getMapperQualifierLoc());
+ if (!QualifierLoc)
+ return true;
+ }
+ MapperIdScopeSpec.Adopt(QualifierLoc);
+ MapperIdInfo = C->getMapperIdInfo();
+ if (MapperIdInfo.getName()) {
+ MapperIdInfo = TT.getDerived().TransformDeclarationNameInfo(MapperIdInfo);
+ if (!MapperIdInfo.getName())
+ return true;
+ }
+ // Build a list of all candidate OMPDeclareMapperDecls, which is provided by
+ // the previous user-defined mapper lookup in dependent environment.
+ for (auto *E : C->mapperlists()) {
+ // Transform all the decls.
+ if (E) {
+ auto *ULE = cast<UnresolvedLookupExpr>(E);
+ UnresolvedSet<8> Decls;
+ for (auto *D : ULE->decls()) {
+ NamedDecl *InstD =
+ cast<NamedDecl>(TT.getDerived().TransformDecl(E->getExprLoc(), D));
+ Decls.addDecl(InstD, InstD->getAccess());
+ }
+ UnresolvedMappers.push_back(UnresolvedLookupExpr::Create(
+ TT.getSema().Context, /*NamingClass=*/nullptr,
+ MapperIdScopeSpec.getWithLocInContext(TT.getSema().Context),
+ MapperIdInfo, /*ADL=*/true, ULE->isOverloaded(), Decls.begin(),
+ Decls.end()));
+ } else {
+ UnresolvedMappers.push_back(nullptr);
+ }
+ }
+ return false;
+}
+
template <typename Derived>
OMPClause *TreeTransform<Derived>::TransformOMPMapClause(OMPMapClause *C) {
+ OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+ llvm::SmallVector<Expr *, 16> Vars;
+ CXXScopeSpec MapperIdScopeSpec;
+ DeclarationNameInfo MapperIdInfo;
+ llvm::SmallVector<Expr *, 16> UnresolvedMappers;
+ if (transformOMPMappableExprListClause<Derived, OMPMapClause>(
+ *this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers))
+ return nullptr;
+ return getDerived().RebuildOMPMapClause(
+ C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), MapperIdScopeSpec,
+ MapperIdInfo, C->getMapType(), C->isImplicitMapType(), C->getMapLoc(),
+ C->getColonLoc(), Vars, Locs, UnresolvedMappers);
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPAllocateClause(OMPAllocateClause *C) {
+ Expr *Allocator = C->getAllocator();
+ if (Allocator) {
+ ExprResult AllocatorRes = getDerived().TransformExpr(Allocator);
+ if (AllocatorRes.isInvalid())
+ return nullptr;
+ Allocator = AllocatorRes.get();
+ }
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
for (auto *VE : C->varlists()) {
@@ -8807,10 +9029,9 @@ OMPClause *TreeTransform<Derived>::TransformOMPMapClause(OMPMapClause *C) {
return nullptr;
Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPMapClause(
- C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), C->getMapType(),
- C->isImplicitMapType(), C->getMapLoc(), C->getColonLoc(), Vars,
- C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+ return getDerived().RebuildOMPAllocateClause(
+ Allocator, Vars, C->getBeginLoc(), C->getLParenLoc(), C->getColonLoc(),
+ C->getEndLoc());
}
template <typename Derived>
@@ -8891,30 +9112,30 @@ TreeTransform<Derived>::TransformOMPDefaultmapClause(OMPDefaultmapClause *C) {
template <typename Derived>
OMPClause *TreeTransform<Derived>::TransformOMPToClause(OMPToClause *C) {
+ OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
llvm::SmallVector<Expr *, 16> Vars;
- Vars.reserve(C->varlist_size());
- for (auto *VE : C->varlists()) {
- ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
- if (EVar.isInvalid())
- return 0;
- Vars.push_back(EVar.get());
- }
- return getDerived().RebuildOMPToClause(Vars, C->getBeginLoc(),
- C->getLParenLoc(), C->getEndLoc());
+ CXXScopeSpec MapperIdScopeSpec;
+ DeclarationNameInfo MapperIdInfo;
+ llvm::SmallVector<Expr *, 16> UnresolvedMappers;
+ if (transformOMPMappableExprListClause<Derived, OMPToClause>(
+ *this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers))
+ return nullptr;
+ return getDerived().RebuildOMPToClause(Vars, MapperIdScopeSpec, MapperIdInfo,
+ Locs, UnresolvedMappers);
}
template <typename Derived>
OMPClause *TreeTransform<Derived>::TransformOMPFromClause(OMPFromClause *C) {
+ OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
llvm::SmallVector<Expr *, 16> Vars;
- Vars.reserve(C->varlist_size());
- for (auto *VE : C->varlists()) {
- ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
- if (EVar.isInvalid())
- return 0;
- Vars.push_back(EVar.get());
- }
- return getDerived().RebuildOMPFromClause(Vars, C->getBeginLoc(),
- C->getLParenLoc(), C->getEndLoc());
+ CXXScopeSpec MapperIdScopeSpec;
+ DeclarationNameInfo MapperIdInfo;
+ llvm::SmallVector<Expr *, 16> UnresolvedMappers;
+ if (transformOMPMappableExprListClause<Derived, OMPFromClause>(
+ *this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers))
+ return nullptr;
+ return getDerived().RebuildOMPFromClause(
+ Vars, MapperIdScopeSpec, MapperIdInfo, Locs, UnresolvedMappers);
}
template <typename Derived>
@@ -8928,8 +9149,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPUseDevicePtrClause(
return nullptr;
Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPUseDevicePtrClause(
- Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+ OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+ return getDerived().RebuildOMPUseDevicePtrClause(Vars, Locs);
}
template <typename Derived>
@@ -8943,8 +9164,8 @@ TreeTransform<Derived>::TransformOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
return nullptr;
Vars.push_back(EVar.get());
}
- return getDerived().RebuildOMPIsDevicePtrClause(
- Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+ OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+ return getDerived().RebuildOMPIsDevicePtrClause(Vars, Locs);
}
//===----------------------------------------------------------------------===//
@@ -9072,10 +9293,10 @@ TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) {
SmallVector<Expr *, 4> AssocExprs;
SmallVector<TypeSourceInfo *, 4> AssocTypes;
- for (unsigned i = 0; i != E->getNumAssocs(); ++i) {
- TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i);
- if (TS) {
- TypeSourceInfo *AssocType = getDerived().TransformType(TS);
+ for (const GenericSelectionExpr::Association &Assoc : E->associations()) {
+ TypeSourceInfo *TSI = Assoc.getTypeSourceInfo();
+ if (TSI) {
+ TypeSourceInfo *AssocType = getDerived().TransformType(TSI);
if (!AssocType)
return ExprError();
AssocTypes.push_back(AssocType);
@@ -9083,7 +9304,8 @@ TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) {
AssocTypes.push_back(nullptr);
}
- ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i));
+ ExprResult AssocExpr =
+ getDerived().TransformExpr(Assoc.getAssociationExpr());
if (AssocExpr.isInvalid())
return ExprError();
AssocExprs.push_back(AssocExpr.get());
@@ -9974,6 +10196,19 @@ TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) {
return getDerived().TransformCallExpr(E);
}
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformSourceLocExpr(SourceLocExpr *E) {
+ bool NeedRebuildFunc = E->getIdentKind() == SourceLocExpr::Function &&
+ getSema().CurContext != E->getParentContext();
+
+ if (!getDerived().AlwaysRebuild() && !NeedRebuildFunc)
+ return E;
+
+ return getDerived().RebuildSourceLocExpr(E->getIdentKind(), E->getBeginLoc(),
+ E->getEndLoc(),
+ getSema().CurContext);
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) {
@@ -10032,6 +10267,22 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformBuiltinBitCastExpr(BuiltinBitCastExpr *BCE) {
+ TypeSourceInfo *TSI =
+ getDerived().TransformType(BCE->getTypeInfoAsWritten());
+ if (!TSI)
+ return ExprError();
+
+ ExprResult Sub = getDerived().TransformExpr(BCE->getSubExpr());
+ if (Sub.isInvalid())
+ return ExprError();
+
+ return getDerived().RebuildBuiltinBitCastExpr(BCE->getBeginLoc(), TSI,
+ Sub.get(), BCE->getEndLoc());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) {
return getDerived().TransformCXXNamedCastExpr(E);
}
@@ -10169,8 +10420,9 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
QualType T = getSema().getCurrentThisType();
if (!getDerived().AlwaysRebuild() && T == E->getType()) {
- // Make sure that we capture 'this'.
- getSema().CheckCXXThisCapture(E->getBeginLoc());
+ // Mark it referenced in the new context regardless.
+ // FIXME: this is a bit instantiation-specific.
+ getSema().MarkThisReferenced(E);
return E;
}
@@ -10200,8 +10452,8 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
if (!Param)
return ExprError();
- if (!getDerived().AlwaysRebuild() &&
- Param == E->getParam())
+ if (!getDerived().AlwaysRebuild() && Param == E->getParam() &&
+ E->getUsedContext() == SemaRef.CurContext)
return E;
return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param);
@@ -10215,7 +10467,8 @@ TreeTransform<Derived>::TransformCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
if (!Field)
return ExprError();
- if (!getDerived().AlwaysRebuild() && Field == E->getField())
+ if (!getDerived().AlwaysRebuild() && Field == E->getField() &&
+ E->getUsedContext() == SemaRef.CurContext)
return E;
return getDerived().RebuildCXXDefaultInitExpr(E->getExprLoc(), Field);
@@ -10248,9 +10501,16 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
return ExprError();
// Transform the size of the array we're allocating (if any).
- ExprResult ArraySize = getDerived().TransformExpr(E->getArraySize());
- if (ArraySize.isInvalid())
- return ExprError();
+ Optional<Expr *> ArraySize;
+ if (Optional<Expr *> OldArraySize = E->getArraySize()) {
+ ExprResult NewArraySize;
+ if (*OldArraySize) {
+ NewArraySize = getDerived().TransformExpr(*OldArraySize);
+ if (NewArraySize.isInvalid())
+ return ExprError();
+ }
+ ArraySize = NewArraySize.get();
+ }
// Transform the placement arguments (if any).
bool ArgumentChanged = false;
@@ -10287,7 +10547,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
if (!getDerived().AlwaysRebuild() &&
AllocTypeInfo == E->getAllocatedTypeSourceInfo() &&
- ArraySize.get() == E->getArraySize() &&
+ ArraySize == E->getArraySize() &&
NewInit.get() == OldInit &&
OperatorNew == E->getOperatorNew() &&
OperatorDelete == E->getOperatorDelete() &&
@@ -10314,7 +10574,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
}
QualType AllocType = AllocTypeInfo->getType();
- if (!ArraySize.get()) {
+ if (!ArraySize) {
// If no array size was specified, but the new expression was
// instantiated with an array type (e.g., "new T" where T is
// instantiated with "int[4]"), extract the outer bound from the
@@ -10342,7 +10602,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
E->getBeginLoc(), E->isGlobalNew(),
/*FIXME:*/ E->getBeginLoc(), PlacementArgs,
/*FIXME:*/ E->getBeginLoc(), E->getTypeIdParens(), AllocType,
- AllocTypeInfo, ArraySize.get(), E->getDirectInitRange(), NewInit.get());
+ AllocTypeInfo, ArraySize, E->getDirectInitRange(), NewInit.get());
}
template<typename Derived>
@@ -10984,33 +11244,78 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
// Transform any init-capture expressions before entering the scope of the
// lambda body, because they are not semantically within that scope.
typedef std::pair<ExprResult, QualType> InitCaptureInfoTy;
- SmallVector<InitCaptureInfoTy, 8> InitCaptureExprsAndTypes;
- InitCaptureExprsAndTypes.resize(E->explicit_capture_end() -
- E->explicit_capture_begin());
+ struct TransformedInitCapture {
+ // The location of the ... if the result is retaining a pack expansion.
+ SourceLocation EllipsisLoc;
+ // Zero or more expansions of the init-capture.
+ SmallVector<InitCaptureInfoTy, 4> Expansions;
+ };
+ SmallVector<TransformedInitCapture, 4> InitCaptures;
+ InitCaptures.resize(E->explicit_capture_end() - E->explicit_capture_begin());
for (LambdaExpr::capture_iterator C = E->capture_begin(),
CEnd = E->capture_end();
C != CEnd; ++C) {
if (!E->isInitCapture(C))
continue;
- EnterExpressionEvaluationContext EEEC(
- getSema(), Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
- ExprResult NewExprInitResult = getDerived().TransformInitializer(
- C->getCapturedVar()->getInit(),
- C->getCapturedVar()->getInitStyle() == VarDecl::CallInit);
-
- if (NewExprInitResult.isInvalid())
- return ExprError();
- Expr *NewExprInit = NewExprInitResult.get();
+ TransformedInitCapture &Result = InitCaptures[C - E->capture_begin()];
VarDecl *OldVD = C->getCapturedVar();
- QualType NewInitCaptureType =
- getSema().buildLambdaInitCaptureInitialization(
- C->getLocation(), OldVD->getType()->isReferenceType(),
- OldVD->getIdentifier(),
- C->getCapturedVar()->getInitStyle() != VarDecl::CInit, NewExprInit);
- NewExprInitResult = NewExprInit;
- InitCaptureExprsAndTypes[C - E->capture_begin()] =
- std::make_pair(NewExprInitResult, NewInitCaptureType);
+
+ auto SubstInitCapture = [&](SourceLocation EllipsisLoc,
+ Optional<unsigned> NumExpansions) {
+ ExprResult NewExprInitResult = getDerived().TransformInitializer(
+ OldVD->getInit(), OldVD->getInitStyle() == VarDecl::CallInit);
+
+ if (NewExprInitResult.isInvalid()) {
+ Result.Expansions.push_back(InitCaptureInfoTy(ExprError(), QualType()));
+ return;
+ }
+ Expr *NewExprInit = NewExprInitResult.get();
+
+ QualType NewInitCaptureType =
+ getSema().buildLambdaInitCaptureInitialization(
+ C->getLocation(), OldVD->getType()->isReferenceType(),
+ EllipsisLoc, NumExpansions, OldVD->getIdentifier(),
+ C->getCapturedVar()->getInitStyle() != VarDecl::CInit,
+ NewExprInit);
+ Result.Expansions.push_back(
+ InitCaptureInfoTy(NewExprInit, NewInitCaptureType));
+ };
+
+ // If this is an init-capture pack, consider expanding the pack now.
+ if (OldVD->isParameterPack()) {
+ PackExpansionTypeLoc ExpansionTL = OldVD->getTypeSourceInfo()
+ ->getTypeLoc()
+ .castAs<PackExpansionTypeLoc>();
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ SemaRef.collectUnexpandedParameterPacks(OldVD->getInit(), Unexpanded);
+
+ // Determine whether the set of unexpanded parameter packs can and should
+ // be expanded.
+ bool Expand = true;
+ bool RetainExpansion = false;
+ Optional<unsigned> OrigNumExpansions =
+ ExpansionTL.getTypePtr()->getNumExpansions();
+ Optional<unsigned> NumExpansions = OrigNumExpansions;
+ if (getDerived().TryExpandParameterPacks(
+ ExpansionTL.getEllipsisLoc(),
+ OldVD->getInit()->getSourceRange(), Unexpanded, Expand,
+ RetainExpansion, NumExpansions))
+ return ExprError();
+ if (Expand) {
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
+ SubstInitCapture(SourceLocation(), None);
+ }
+ }
+ if (!Expand || RetainExpansion) {
+ ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+ SubstInitCapture(ExpansionTL.getEllipsisLoc(), NumExpansions);
+ Result.EllipsisLoc = ExpansionTL.getEllipsisLoc();
+ }
+ } else {
+ SubstInitCapture(SourceLocation(), None);
+ }
}
// Transform the template parameters, and add them to the current
@@ -11048,19 +11353,25 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
LSI->GLTemplateParameterList = TPL;
// Create the local class that will describe the lambda.
+ CXXRecordDecl *OldClass = E->getLambdaClass();
CXXRecordDecl *Class
= getSema().createLambdaClosureType(E->getIntroducerRange(),
NewCallOpTSI,
/*KnownDependent=*/false,
E->getCaptureDefault());
- getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
+ getDerived().transformedLocalDecl(OldClass, {Class});
+
+ Optional<std::pair<unsigned, Decl*>> Mangling;
+ if (getDerived().ReplacingOriginal())
+ Mangling = std::make_pair(OldClass->getLambdaManglingNumber(),
+ OldClass->getLambdaContextDecl());
// Build the call operator.
CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(
Class, E->getIntroducerRange(), NewCallOpTSI,
E->getCallOperator()->getEndLoc(),
NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
- E->getCallOperator()->isConstexpr());
+ E->getCallOperator()->getConstexprKind(), Mangling);
LSI->CallOperator = NewCallOperator;
@@ -11078,7 +11389,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
}
getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
- getDerived().transformedLocalDecl(E->getCallOperator(), NewCallOperator);
+ getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
// Introduce the context of the call operator.
Sema::ContextRAII SavedContext(getSema(), NewCallOperator,
@@ -11096,16 +11407,13 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
bool Invalid = false;
// Transform captures.
- bool FinishedExplicitCaptures = false;
for (LambdaExpr::capture_iterator C = E->capture_begin(),
CEnd = E->capture_end();
C != CEnd; ++C) {
// When we hit the first implicit capture, tell Sema that we've finished
// the list of explicit captures.
- if (!FinishedExplicitCaptures && C->isImplicit()) {
- getSema().finishLambdaExplicitCaptures(LSI);
- FinishedExplicitCaptures = true;
- }
+ if (C->isImplicit())
+ break;
// Capturing 'this' is trivial.
if (C->capturesThis()) {
@@ -11121,24 +11429,33 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
// Rebuild init-captures, including the implied field declaration.
if (E->isInitCapture(C)) {
- InitCaptureInfoTy InitExprTypePair =
- InitCaptureExprsAndTypes[C - E->capture_begin()];
- ExprResult Init = InitExprTypePair.first;
- QualType InitQualType = InitExprTypePair.second;
- if (Init.isInvalid() || InitQualType.isNull()) {
- Invalid = true;
- continue;
- }
+ TransformedInitCapture &NewC = InitCaptures[C - E->capture_begin()];
+
VarDecl *OldVD = C->getCapturedVar();
- VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl(
- OldVD->getLocation(), InitExprTypePair.second, OldVD->getIdentifier(),
- OldVD->getInitStyle(), Init.get());
- if (!NewVD)
- Invalid = true;
- else {
- getDerived().transformedLocalDecl(OldVD, NewVD);
+ llvm::SmallVector<Decl*, 4> NewVDs;
+
+ for (InitCaptureInfoTy &Info : NewC.Expansions) {
+ ExprResult Init = Info.first;
+ QualType InitQualType = Info.second;
+ if (Init.isInvalid() || InitQualType.isNull()) {
+ Invalid = true;
+ break;
+ }
+ VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl(
+ OldVD->getLocation(), InitQualType, NewC.EllipsisLoc,
+ OldVD->getIdentifier(), OldVD->getInitStyle(), Init.get());
+ if (!NewVD) {
+ Invalid = true;
+ break;
+ }
+ NewVDs.push_back(NewVD);
+ getSema().addInitCapture(LSI, NewVD);
}
- getSema().buildInitCaptureField(LSI, NewVD);
+
+ if (Invalid)
+ break;
+
+ getDerived().transformedLocalDecl(OldVD, NewVDs);
continue;
}
@@ -11205,17 +11522,16 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind,
EllipsisLoc);
}
- if (!FinishedExplicitCaptures)
- getSema().finishLambdaExplicitCaptures(LSI);
+ getSema().finishLambdaExplicitCaptures(LSI);
- // Enter a new evaluation context to insulate the lambda from any
- // cleanups from the enclosing full-expression.
+ // FIXME: Sema's lambda-building mechanism expects us to push an expression
+ // evaluation context even if we're not transforming the function body.
getSema().PushExpressionEvaluationContext(
Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
// Instantiate the body of the lambda expression.
StmtResult Body =
- Invalid ? StmtError() : getDerived().TransformStmt(E->getBody());
+ Invalid ? StmtError() : getDerived().TransformLambdaBody(E, E->getBody());
// ActOnLambda* will pop the function scope for us.
FuncScopeCleanup.disable();
@@ -11240,6 +11556,52 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
}
template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformLambdaBody(LambdaExpr *E, Stmt *S) {
+ return TransformStmt(S);
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::SkipLambdaBody(LambdaExpr *E, Stmt *S) {
+ // Transform captures.
+ for (LambdaExpr::capture_iterator C = E->capture_begin(),
+ CEnd = E->capture_end();
+ C != CEnd; ++C) {
+ // When we hit the first implicit capture, tell Sema that we've finished
+ // the list of explicit captures.
+ if (!C->isImplicit())
+ continue;
+
+ // Capturing 'this' is trivial.
+ if (C->capturesThis()) {
+ getSema().CheckCXXThisCapture(C->getLocation(), C->isExplicit(),
+ /*BuildAndDiagnose*/ true, nullptr,
+ C->getCaptureKind() == LCK_StarThis);
+ continue;
+ }
+ // Captured expression will be recaptured during captured variables
+ // rebuilding.
+ if (C->capturesVLAType())
+ continue;
+
+ assert(C->capturesVariable() && "unexpected kind of lambda capture");
+ assert(!E->isInitCapture(C) && "implicit init-capture?");
+
+ // Transform the captured variable.
+ VarDecl *CapturedVar = cast_or_null<VarDecl>(
+ getDerived().TransformDecl(C->getLocation(), C->getCapturedVar()));
+ if (!CapturedVar || CapturedVar->isInvalidDecl())
+ return StmtError();
+
+ // Capture the transformed variable.
+ getSema().tryCaptureVariable(CapturedVar, C->getLocation());
+ }
+
+ return S;
+}
+
+template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
CXXUnresolvedConstructExpr *E) {
@@ -11659,7 +12021,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
// be expanded.
bool Expand = true;
bool RetainExpansion = false;
- Optional<unsigned> NumExpansions;
+ Optional<unsigned> OrigNumExpansions = E->getNumExpansions(),
+ NumExpansions = OrigNumExpansions;
if (getDerived().TryExpandParameterPacks(E->getEllipsisLoc(),
Pattern->getSourceRange(),
Unexpanded,
@@ -11688,7 +12051,7 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
return getDerived().RebuildCXXFoldExpr(
E->getBeginLoc(), LHS.get(), E->getOperator(), E->getEllipsisLoc(),
- RHS.get(), E->getEndLoc());
+ RHS.get(), E->getEndLoc(), NumExpansions);
}
// The transform has determined that we should perform an elementwise
@@ -11709,7 +12072,7 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
Result = getDerived().RebuildCXXFoldExpr(
E->getBeginLoc(), Out.get(), E->getOperator(), E->getEllipsisLoc(),
- Result.get(), E->getEndLoc());
+ Result.get(), E->getEndLoc(), OrigNumExpansions);
if (Result.isInvalid())
return true;
}
@@ -11726,7 +12089,8 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
Result = getDerived().RebuildCXXFoldExpr(
E->getBeginLoc(), LeftFold ? Result.get() : Out.get(),
E->getOperator(), E->getEllipsisLoc(),
- LeftFold ? Out.get() : Result.get(), E->getEndLoc());
+ LeftFold ? Out.get() : Result.get(), E->getEndLoc(),
+ OrigNumExpansions);
} else if (Result.isUsable()) {
// We've got down to a single element; build a binary operator.
Result = getDerived().RebuildBinaryOperator(
@@ -11751,7 +12115,7 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
Result = getDerived().RebuildCXXFoldExpr(
E->getBeginLoc(), Result.get(), E->getOperator(), E->getEllipsisLoc(),
- Out.get(), E->getEndLoc());
+ Out.get(), E->getEndLoc(), OrigNumExpansions);
if (Result.isInvalid())
return true;
}
@@ -12277,8 +12641,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
VarDecl *oldCapture = I.getVariable();
// Ignore parameter packs.
- if (isa<ParmVarDecl>(oldCapture) &&
- cast<ParmVarDecl>(oldCapture)->isParameterPack())
+ if (oldCapture->isParameterPack())
continue;
VarDecl *newCapture =