summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/Sema/SemaLambda.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Sema/SemaLambda.cpp')
-rw-r--r--gnu/llvm/tools/clang/lib/Sema/SemaLambda.cpp305
1 files changed, 184 insertions, 121 deletions
diff --git a/gnu/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/gnu/llvm/tools/clang/lib/Sema/SemaLambda.cpp
index 19d2de71972..440567e032e 100644
--- a/gnu/llvm/tools/clang/lib/Sema/SemaLambda.cpp
+++ b/gnu/llvm/tools/clang/lib/Sema/SemaLambda.cpp
@@ -24,29 +24,29 @@
using namespace clang;
using namespace sema;
-/// \brief Examines the FunctionScopeInfo stack to determine the nearest
-/// enclosing lambda (to the current lambda) that is 'capture-ready' for
+/// Examines the FunctionScopeInfo stack to determine the nearest
+/// enclosing lambda (to the current lambda) that is 'capture-ready' for
/// the variable referenced in the current lambda (i.e. \p VarToCapture).
/// If successful, returns the index into Sema's FunctionScopeInfo stack
/// of the capture-ready lambda's LambdaScopeInfo.
-///
-/// Climbs down the stack of lambdas (deepest nested lambda - i.e. current
+///
+/// Climbs down the stack of lambdas (deepest nested lambda - i.e. current
/// lambda - is on top) to determine the index of the nearest enclosing/outer
-/// lambda that is ready to capture the \p VarToCapture being referenced in
-/// the current lambda.
+/// lambda that is ready to capture the \p VarToCapture being referenced in
+/// the current lambda.
/// As we climb down the stack, we want the index of the first such lambda -
-/// that is the lambda with the highest index that is 'capture-ready'.
-///
+/// that is the lambda with the highest index that is 'capture-ready'.
+///
/// A lambda 'L' is capture-ready for 'V' (var or this) if:
/// - its enclosing context is non-dependent
/// - and if the chain of lambdas between L and the lambda in which
-/// V is potentially used (i.e. the lambda at the top of the scope info
+/// V is potentially used (i.e. the lambda at the top of the scope info
/// stack), can all capture or have already captured V.
/// If \p VarToCapture is 'null' then we are trying to capture 'this'.
-///
+///
/// Note that a lambda that is deemed 'capture-ready' still needs to be checked
/// for whether it is 'capture-capable' (see
-/// getStackIndexOfNearestEnclosingCaptureCapableLambda), before it can truly
+/// getStackIndexOfNearestEnclosingCaptureCapableLambda), before it can truly
/// capture.
///
/// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a
@@ -120,7 +120,7 @@ getStackIndexOfNearestEnclosingCaptureReadyLambda(
return NoLambdaIsCaptureReady;
}
EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC);
-
+
assert(CurScopeIndex);
--CurScopeIndex;
} while (!EnclosingDC->isTranslationUnit() &&
@@ -135,14 +135,14 @@ getStackIndexOfNearestEnclosingCaptureReadyLambda(
return NoLambdaIsCaptureReady;
}
-/// \brief Examines the FunctionScopeInfo stack to determine the nearest
-/// enclosing lambda (to the current lambda) that is 'capture-capable' for
+/// Examines the FunctionScopeInfo stack to determine the nearest
+/// enclosing lambda (to the current lambda) that is 'capture-capable' for
/// the variable referenced in the current lambda (i.e. \p VarToCapture).
/// If successful, returns the index into Sema's FunctionScopeInfo stack
/// of the capture-capable lambda's LambdaScopeInfo.
///
/// Given the current stack of lambdas being processed by Sema and
-/// the variable of interest, to identify the nearest enclosing lambda (to the
+/// the variable of interest, to identify the nearest enclosing lambda (to the
/// current lambda at the top of the stack) that can truly capture
/// a variable, it has to have the following two properties:
/// a) 'capture-ready' - be the innermost lambda that is 'capture-ready':
@@ -175,7 +175,7 @@ Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda(
VarDecl *VarToCapture, Sema &S) {
const Optional<unsigned> NoLambdaIsCaptureCapable;
-
+
const Optional<unsigned> OptionalStackIndex =
getStackIndexOfNearestEnclosingCaptureReadyLambda(FunctionScopes,
VarToCapture);
@@ -190,7 +190,7 @@ Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda(
const sema::LambdaScopeInfo *const CaptureReadyLambdaLSI =
cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambda]);
-
+
// If VarToCapture is null, we are attempting to capture 'this'
const bool IsCapturingThis = !VarToCapture;
const bool IsCapturingVariable = !IsCapturingThis;
@@ -220,7 +220,7 @@ Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda(
&IndexOfCaptureReadyLambda);
if (!CanCaptureThis)
return NoLambdaIsCaptureCapable;
- }
+ }
return IndexOfCaptureReadyLambda;
}
@@ -245,35 +245,35 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
- bool KnownDependent,
+ bool KnownDependent,
LambdaCaptureDefault CaptureDefault) {
DeclContext *DC = CurContext;
while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
DC = DC->getParent();
bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(),
- *this);
+ *this);
// Start constructing the lambda class.
CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info,
IntroducerRange.getBegin(),
- KnownDependent,
- IsGenericLambda,
+ KnownDependent,
+ IsGenericLambda,
CaptureDefault);
DC->addDecl(Class);
return Class;
}
-/// \brief Determine whether the given context is or is enclosed in an inline
+/// Determine whether the given context is or is enclosed in an inline
/// function.
static bool isInInlineFunction(const DeclContext *DC) {
while (!DC->isFileContext()) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
if (FD->isInlined())
return true;
-
+
DC = DC->getLexicalParent();
}
-
+
return false;
}
@@ -379,10 +379,10 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
ArrayRef<ParmVarDecl *> Params,
const bool IsConstexprSpecified) {
QualType MethodType = MethodTypeInfo->getType();
- TemplateParameterList *TemplateParams =
+ TemplateParameterList *TemplateParams =
getGenericLambdaTemplateParameterList(getCurLambda(), *this);
// If a lambda appears in a dependent context or is a generic lambda (has
- // template parameters) and has an 'auto' return type, deduce it to a
+ // template parameters) and has an 'auto' return type, deduce it to a
// dependent type.
if (Class->isDependentContext() || TemplateParams) {
const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
@@ -395,9 +395,9 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
}
// C++11 [expr.prim.lambda]p5:
- // The closure type for a lambda-expression has a public inline function
+ // The closure type for a lambda-expression has a public inline function
// call operator (13.5.4) whose parameters and return type are described by
- // the lambda-expression's parameter-declaration-clause and
+ // the lambda-expression's parameter-declaration-clause and
// trailing-return-type respectively.
DeclarationName MethodName
= Context.DeclarationNames.getCXXOperatorName(OO_Call);
@@ -408,7 +408,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
= IntroducerRange.getEnd().getRawEncoding();
CXXMethodDecl *Method
= CXXMethodDecl::Create(Context, Class, EndLoc,
- DeclarationNameInfo(MethodName,
+ DeclarationNameInfo(MethodName,
IntroducerRange.getBegin(),
MethodNameLoc),
MethodType, MethodTypeInfo,
@@ -417,14 +417,14 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
IsConstexprSpecified,
EndLoc);
Method->setAccess(AS_public);
-
+
// Temporarily set the lexical declaration context to the current
// context, so that the Scope stack matches the lexical nesting.
- Method->setLexicalDeclContext(CurContext);
+ Method->setLexicalDeclContext(CurContext);
// Create a function template if we have a template parameter list
FunctionTemplateDecl *const TemplateMethod = TemplateParams ?
FunctionTemplateDecl::Create(Context, Class,
- Method->getLocation(), MethodName,
+ Method->getLocation(), MethodName,
TemplateParams,
Method) : nullptr;
if (TemplateMethod) {
@@ -432,7 +432,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
TemplateMethod->setAccess(AS_public);
Method->setDescribedFunctionTemplate(TemplateMethod);
}
-
+
// Add parameters.
if (!Params.empty()) {
Method->setParams(Params);
@@ -493,16 +493,16 @@ void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
LSI->finishedExplicitCaptures();
}
-void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
+void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
// Introduce our parameters into the function scope
- for (unsigned p = 0, NumParams = CallOperator->getNumParams();
+ for (unsigned p = 0, NumParams = CallOperator->getNumParams();
p < NumParams; ++p) {
ParmVarDecl *Param = CallOperator->getParamDecl(p);
-
+
// If this has an identifier, add it to the scope stack.
if (CurScope && Param->getIdentifier()) {
CheckShadow(CurScope, Param);
-
+
PushOnScopeChains(Param, CurScope);
}
}
@@ -637,7 +637,7 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns,
void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
assert(CSI.HasImplicitReturnType);
// If it was ever a placeholder, it had to been deduced to DependentTy.
- assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType());
+ assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType());
assert((!isa<LambdaScopeInfo>(CSI) || !getLangOpts().CPlusPlus14) &&
"lambda expressions use auto deduction in C++14 onwards");
@@ -692,9 +692,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
}
// Third case: only one return statement. Don't bother doing extra work!
- SmallVectorImpl<ReturnStmt*>::iterator I = CSI.Returns.begin(),
- E = CSI.Returns.end();
- if (I+1 == E)
+ if (CSI.Returns.size() == 1)
return;
// General case: many return statements.
@@ -703,15 +701,22 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
// We require the return types to strictly match here.
// Note that we've already done the required promotions as part of
// processing the return statement.
- for (; I != E; ++I) {
- const ReturnStmt *RS = *I;
+ for (const ReturnStmt *RS : CSI.Returns) {
const Expr *RetE = RS->getRetValue();
QualType ReturnType =
(RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType();
if (Context.getCanonicalFunctionResultType(ReturnType) ==
- Context.getCanonicalFunctionResultType(CSI.ReturnType))
+ Context.getCanonicalFunctionResultType(CSI.ReturnType)) {
+ // Use the return type with the strictest possible nullability annotation.
+ auto RetTyNullability = ReturnType->getNullability(Ctx);
+ auto BlockNullability = CSI.ReturnType->getNullability(Ctx);
+ if (BlockNullability &&
+ (!RetTyNullability ||
+ hasWeakerNullability(*RetTyNullability, *BlockNullability)))
+ CSI.ReturnType = ReturnType;
continue;
+ }
// FIXME: This is a poor diagnostic for ReturnStmts without expressions.
// TODO: It's possible that the *first* return is the divergent one.
@@ -846,7 +851,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
SmallVector<ParmVarDecl *, 8> Params;
if (ParamInfo.getNumTypeObjects() == 0) {
// C++11 [expr.prim.lambda]p4:
- // If a lambda-expression does not include a lambda-declarator, it is as
+ // If a lambda-expression does not include a lambda-declarator, it is as
// if the lambda-declarator were ().
FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention(
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
@@ -873,8 +878,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
// C++11 [expr.prim.lambda]p5:
- // This function call operator is declared const (9.3.1) if and only if
- // the lambda-expression's parameter-declaration-clause is not followed
+ // This function call operator is declared const (9.3.1) if and only if
+ // the lambda-expression's parameter-declaration-clause is not followed
// by mutable. It is neither virtual nor declared volatile. [...]
if (!FTI.hasMutableQualifier())
FTI.TypeQuals |= DeclSpec::TQ_const;
@@ -904,8 +909,16 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
ParamInfo.getDeclSpec().isConstexprSpecified());
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
-
- // Attributes on the lambda apply to the method.
+
+ // This represents the function body for the lambda function, check if we
+ // have to apply optnone due to a pragma.
+ AddRangeBasedOptnone(Method);
+
+ // code_seg attribute on lambda apply to the method.
+ if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true))
+ Method->addAttr(A);
+
+ // Attributes on the lambda apply to the method.
ProcessDeclAttributes(CurScope, Method, ParamInfo);
// CUDA lambdas get implicit attributes based on the scope in which they're
@@ -915,7 +928,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// Introduce the function call operator as the current declaration context.
PushDeclContext(CurScope, Method);
-
+
// Build the lambda scope.
buildLambdaScope(LSI, Method, Intro.Range, Intro.Default, Intro.DefaultLoc,
ExplicitParams, ExplicitResultType, !Method->isConst());
@@ -946,13 +959,13 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
for (auto C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E;
PrevCaptureLoc = C->Loc, ++C) {
if (C->Kind == LCK_This || C->Kind == LCK_StarThis) {
- if (C->Kind == LCK_StarThis)
+ if (C->Kind == LCK_StarThis)
Diag(C->Loc, !getLangOpts().CPlusPlus17
? diag::ext_star_this_lambda_capture_cxx17
: diag::warn_cxx14_compat_star_this_lambda_capture);
// C++11 [expr.prim.lambda]p8:
- // An identifier or this shall not appear more than once in a
+ // An identifier or this shall not appear more than once in a
// lambda-capture.
if (LSI->isCXXThisCaptured()) {
Diag(C->Loc, diag::err_capture_more_than_once)
@@ -980,10 +993,12 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
Diag(C->Loc, diag::err_this_capture) << true;
continue;
}
-
+
CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true,
/*FunctionScopeIndexToStopAtPtr*/ nullptr,
C->Kind == LCK_StarThis);
+ if (!LSI->Captures.empty())
+ LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
continue;
}
@@ -1003,9 +1018,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// If the initializer expression is usable, but the InitCaptureType
// is not, then an error has occurred - so ignore the capture for now.
// for e.g., [n{0}] { }; <-- if no <initializer_list> is included.
- // FIXME: we should create the init capture variable and mark it invalid
+ // FIXME: we should create the init capture variable and mark it invalid
// in this case.
- if (C->InitCaptureType.get().isNull())
+ if (C->InitCaptureType.get().isNull())
continue;
unsigned InitStyle;
@@ -1035,7 +1050,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
"init capture has valid but null init?");
// C++11 [expr.prim.lambda]p8:
- // If a lambda-capture includes a capture-default that is &, the
+ // If a lambda-capture includes a capture-default that is &, the
// identifiers in the lambda-capture shall not be preceded by &.
// If a lambda-capture includes a capture-default that is =, [...]
// each identifier it contains shall be preceded by &.
@@ -1116,7 +1131,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
} else {
Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< SourceRange(C->Loc);
-
+
// Just ignore the ellipsis.
}
} else if (Var->isParameterPack()) {
@@ -1130,6 +1145,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
TryCapture_ExplicitByVal;
tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
}
+ if (!LSI->Captures.empty())
+ LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
}
finishLambdaExplicitCaptures(LSI);
@@ -1161,7 +1178,7 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
Class->setInvalidDecl();
SmallVector<Decl*, 4> Fields(Class->fields());
ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
- SourceLocation(), nullptr);
+ SourceLocation(), ParsedAttributesView());
CheckCompletedCXXClass(Class);
PopFunctionScopeInfo();
@@ -1172,20 +1189,20 @@ QualType Sema::getLambdaConversionFunctionResultType(
// The function type inside the pointer type is the same as the call
// operator with some tweaks. The calling convention is the default free
// function convention, and the type qualifications are lost.
- const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
- CallOpProto->getExtProtoInfo();
+ const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
+ CallOpProto->getExtProtoInfo();
FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
CallingConv CC = Context.getDefaultCallingConvention(
CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
InvokerExtInfo.TypeQuals = 0;
- assert(InvokerExtInfo.RefQualifier == RQ_None &&
+ assert(InvokerExtInfo.RefQualifier == RQ_None &&
"Lambda's call operator should not have a reference qualifier");
return Context.getFunctionType(CallOpProto->getReturnType(),
CallOpProto->getParamTypes(), InvokerExtInfo);
}
-/// \brief Add a lambda's conversion to function pointer, as described in
+/// Add a lambda's conversion to function pointer, as described in
/// C++11 [expr.prim.lambda]p6.
static void addFunctionPointerConversion(Sema &S,
SourceRange IntroducerRange,
@@ -1210,7 +1227,7 @@ static void addFunctionPointerConversion(Sema &S,
/*IsVariadic=*/false, /*IsCXXMethod=*/true));
// The conversion function is always const.
ConvExtInfo.TypeQuals = Qualifiers::Const;
- QualType ConvTy =
+ QualType ConvTy =
S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo);
SourceLocation Loc = IntroducerRange.getBegin();
@@ -1219,8 +1236,8 @@ static void addFunctionPointerConversion(Sema &S,
S.Context.getCanonicalType(PtrToFunctionTy));
DeclarationNameLoc ConvNameLoc;
// Construct a TypeSourceInfo for the conversion function, and wire
- // all the parameters appropriately for the FunctionProtoTypeLoc
- // so that everything works during transformation/instantiation of
+ // all the parameters appropriately for the FunctionProtoTypeLoc
+ // so that everything works during transformation/instantiation of
// generic lambdas.
// The main reason for wiring up the parameters of the conversion
// function with that of the call operator is so that constructs
@@ -1230,46 +1247,46 @@ static void addFunctionPointerConversion(Sema &S,
// return a;
// };
// };
- // int (*fp)(int) = L(5);
+ // int (*fp)(int) = L(5);
// Because the trailing return type can contain DeclRefExprs that refer
- // to the original call operator's variables, we hijack the call
+ // to the original call operator's variables, we hijack the call
// operators ParmVarDecls below.
- TypeSourceInfo *ConvNamePtrToFunctionTSI =
+ TypeSourceInfo *ConvNamePtrToFunctionTSI =
S.Context.getTrivialTypeSourceInfo(PtrToFunctionTy, Loc);
ConvNameLoc.NamedType.TInfo = ConvNamePtrToFunctionTSI;
// The conversion function is a conversion to a pointer-to-function.
TypeSourceInfo *ConvTSI = S.Context.getTrivialTypeSourceInfo(ConvTy, Loc);
- FunctionProtoTypeLoc ConvTL =
+ FunctionProtoTypeLoc ConvTL =
ConvTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
// Get the result of the conversion function which is a pointer-to-function.
- PointerTypeLoc PtrToFunctionTL =
+ PointerTypeLoc PtrToFunctionTL =
ConvTL.getReturnLoc().getAs<PointerTypeLoc>();
// Do the same for the TypeSourceInfo that is used to name the conversion
// operator.
- PointerTypeLoc ConvNamePtrToFunctionTL =
+ PointerTypeLoc ConvNamePtrToFunctionTL =
ConvNamePtrToFunctionTSI->getTypeLoc().getAs<PointerTypeLoc>();
-
+
// Get the underlying function types that the conversion function will
// be converting to (should match the type of the call operator).
- FunctionProtoTypeLoc CallOpConvTL =
+ FunctionProtoTypeLoc CallOpConvTL =
PtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>();
- FunctionProtoTypeLoc CallOpConvNameTL =
+ FunctionProtoTypeLoc CallOpConvNameTL =
ConvNamePtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>();
-
+
// Wire up the FunctionProtoTypeLocs with the call operator's parameters.
// These parameter's are essentially used to transform the name and
// the type of the conversion operator. By using the same parameters
// as the call operator's we don't have to fix any back references that
- // the trailing return type of the call operator's uses (such as
+ // the trailing return type of the call operator's uses (such as
// decltype(some_type<decltype(a)>::type{} + decltype(a){}) etc.)
- // - we can simply use the return type of the call operator, and
- // everything should work.
+ // - we can simply use the return type of the call operator, and
+ // everything should work.
SmallVector<ParmVarDecl *, 4> InvokerParams;
for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
ParmVarDecl *From = CallOperator->getParamDecl(I);
- InvokerParams.push_back(ParmVarDecl::Create(S.Context,
+ InvokerParams.push_back(ParmVarDecl::Create(S.Context,
// Temporarily add to the TU. This is set to the invoker below.
S.Context.getTranslationUnitDecl(),
From->getLocStart(),
@@ -1283,14 +1300,14 @@ static void addFunctionPointerConversion(Sema &S,
CallOpConvNameTL.setParam(I, From);
}
- CXXConversionDecl *Conversion
- = CXXConversionDecl::Create(S.Context, Class, Loc,
- DeclarationNameInfo(ConversionName,
+ CXXConversionDecl *Conversion
+ = CXXConversionDecl::Create(S.Context, Class, Loc,
+ DeclarationNameInfo(ConversionName,
Loc, ConvNameLoc),
- ConvTy,
+ ConvTy,
ConvTSI,
/*isInline=*/true, /*isExplicit=*/false,
- /*isConstexpr=*/S.getLangOpts().CPlusPlus17,
+ /*isConstexpr=*/S.getLangOpts().CPlusPlus17,
CallOperator->getBody()->getLocEnd());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
@@ -1298,7 +1315,7 @@ static void addFunctionPointerConversion(Sema &S,
if (Class->isGenericLambda()) {
// Create a template version of the conversion operator, using the template
// parameter list of the function call operator.
- FunctionTemplateDecl *TemplateCallOperator =
+ FunctionTemplateDecl *TemplateCallOperator =
CallOperator->getDescribedFunctionTemplate();
FunctionTemplateDecl *ConversionTemplate =
FunctionTemplateDecl::Create(S.Context, Class,
@@ -1320,19 +1337,19 @@ static void addFunctionPointerConversion(Sema &S,
// using FunctionTy & Loc and get its TypeLoc as a FunctionProtoTypeLoc
// then rewire the parameters accordingly, by hoisting up the InvokeParams
// loop below and then use its Params to set Invoke->setParams(...) below.
- // This would avoid the 'const' qualifier of the calloperator from
- // contaminating the type of the invoker, which is currently adjusted
+ // This would avoid the 'const' qualifier of the calloperator from
+ // contaminating the type of the invoker, which is currently adjusted
// in SemaTemplateDeduction.cpp:DeduceTemplateArguments. Fixing the
// trailing return type of the invoker would require a visitor to rebuild
// the trailing return type and adjusting all back DeclRefExpr's to refer
// to the new static invoker parameters - not the call operator's.
CXXMethodDecl *Invoke
- = CXXMethodDecl::Create(S.Context, Class, Loc,
- DeclarationNameInfo(InvokerName, Loc),
+ = CXXMethodDecl::Create(S.Context, Class, Loc,
+ DeclarationNameInfo(InvokerName, Loc),
InvokerFunctionTy,
- CallOperator->getTypeSourceInfo(),
+ CallOperator->getTypeSourceInfo(),
SC_Static, /*IsInline=*/true,
- /*IsConstexpr=*/false,
+ /*IsConstexpr=*/false,
CallOperator->getBody()->getLocEnd());
for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I)
InvokerParams[I]->setOwningFunction(Invoke);
@@ -1340,7 +1357,7 @@ static void addFunctionPointerConversion(Sema &S,
Invoke->setAccess(AS_private);
Invoke->setImplicit(true);
if (Class->isGenericLambda()) {
- FunctionTemplateDecl *TemplateCallOperator =
+ FunctionTemplateDecl *TemplateCallOperator =
CallOperator->getDescribedFunctionTemplate();
FunctionTemplateDecl *StaticInvokerTemplate = FunctionTemplateDecl::Create(
S.Context, Class, Loc, InvokerName,
@@ -1354,8 +1371,8 @@ static void addFunctionPointerConversion(Sema &S,
Class->addDecl(Invoke);
}
-/// \brief Add a lambda's conversion to block pointer.
-static void addBlockPointerConversion(Sema &S,
+/// Add a lambda's conversion to block pointer.
+static void addBlockPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
@@ -1375,21 +1392,22 @@ static void addBlockPointerConversion(Sema &S,
S.Context.getCanonicalType(BlockPtrTy));
DeclarationNameLoc NameLoc;
NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc);
- CXXConversionDecl *Conversion
- = CXXConversionDecl::Create(S.Context, Class, Loc,
+ CXXConversionDecl *Conversion
+ = CXXConversionDecl::Create(S.Context, Class, Loc,
DeclarationNameInfo(Name, Loc, NameLoc),
- ConvTy,
+ ConvTy,
S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
/*isInline=*/true, /*isExplicit=*/false,
- /*isConstexpr=*/false,
+ /*isConstexpr=*/false,
CallOperator->getBody()->getLocEnd());
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
Class->addDecl(Conversion);
}
-static ExprResult performLambdaVarCaptureInitialization(
- Sema &S, const LambdaScopeInfo::Capture &Capture, FieldDecl *Field) {
+static ExprResult performLambdaVarCaptureInitialization(Sema &S,
+ const Capture &Capture,
+ FieldDecl *Field) {
assert(Capture.isVariableCapture() && "not a variable capture");
auto *Var = Capture.getVariable();
@@ -1403,7 +1421,7 @@ static ExprResult performLambdaVarCaptureInitialization(
// direct-initialized in increasing subscript order.) These
// initializations are performed in the (unspecified) order in
// which the non-static data members are declared.
-
+
// C++ [expr.prim.lambda]p12:
// An entity captured by a lambda-expression is odr-used (3.2) in
// the scope containing the lambda-expression.
@@ -1419,8 +1437,8 @@ static ExprResult performLambdaVarCaptureInitialization(
InitializationSequence Init(S, Entity, InitKind, Ref);
return Init.Perform(S, Entity, InitKind, Ref);
}
-
-ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
+
+ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Scope *CurScope) {
LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back());
ActOnFinishFunctionBody(LSI.CallOperator, Body);
@@ -1443,7 +1461,7 @@ mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) {
llvm_unreachable("Unknown implicit capture style");
}
-bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) {
+bool Sema::CaptureHasSideEffects(const Capture &From) {
if (!From.isVLATypeCapture()) {
Expr *Init = From.getInitExpr();
if (Init && Init->HasSideEffects(Context))
@@ -1468,12 +1486,13 @@ bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) {
return false;
}
-void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) {
+bool Sema::DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
+ const Capture &From) {
if (CaptureHasSideEffects(From))
- return;
+ return false;
if (From.isVLATypeCapture())
- return;
+ return false;
auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture);
if (From.isThisCapture())
@@ -1481,6 +1500,8 @@ void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) {
else
diag << From.getVariable();
diag << From.isNonODRUsed();
+ diag << FixItHint::CreateRemoval(CaptureRange);
+ return true;
}
ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
@@ -1510,9 +1531,9 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
IsGenericLambda = Class->isGenericLambda();
CallOperator->setLexicalDeclContext(Class);
- Decl *TemplateOrNonTemplateCallOperatorDecl =
- CallOperator->getDescribedFunctionTemplate()
- ? CallOperator->getDescribedFunctionTemplate()
+ Decl *TemplateOrNonTemplateCallOperatorDecl =
+ CallOperator->getDescribedFunctionTemplate()
+ ? CallOperator->getDescribedFunctionTemplate()
: cast<Decl>(CallOperator);
TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);
@@ -1522,22 +1543,64 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// Translate captures.
auto CurField = Class->field_begin();
+ // True if the current capture has a used capture or default before it.
+ bool CurHasPreviousCapture = CaptureDefault != LCD_None;
+ SourceLocation PrevCaptureLoc = CurHasPreviousCapture ?
+ CaptureDefaultLoc : IntroducerRange.getBegin();
+
for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) {
- const LambdaScopeInfo::Capture &From = LSI->Captures[I];
+ const Capture &From = LSI->Captures[I];
+
assert(!From.isBlockCapture() && "Cannot capture __block variables");
bool IsImplicit = I >= LSI->NumExplicitCaptures;
+ // Use source ranges of explicit captures for fixits where available.
+ SourceRange CaptureRange = LSI->ExplicitCaptureRanges[I];
+
// Warn about unused explicit captures.
+ bool IsCaptureUsed = true;
if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) {
// Initialized captures that are non-ODR used may not be eliminated.
bool NonODRUsedInitCapture =
IsGenericLambda && From.isNonODRUsed() && From.getInitExpr();
- if (!NonODRUsedInitCapture)
- DiagnoseUnusedLambdaCapture(From);
+ if (!NonODRUsedInitCapture) {
+ bool IsLast = (I + 1) == LSI->NumExplicitCaptures;
+ SourceRange FixItRange;
+ if (CaptureRange.isValid()) {
+ if (!CurHasPreviousCapture && !IsLast) {
+ // If there are no captures preceding this capture, remove the
+ // following comma.
+ FixItRange = SourceRange(CaptureRange.getBegin(),
+ getLocForEndOfToken(CaptureRange.getEnd()));
+ } else {
+ // Otherwise, remove the comma since the last used capture.
+ FixItRange = SourceRange(getLocForEndOfToken(PrevCaptureLoc),
+ CaptureRange.getEnd());
+ }
+ }
+
+ IsCaptureUsed = !DiagnoseUnusedLambdaCapture(FixItRange, From);
+ }
+ }
+
+ if (CaptureRange.isValid()) {
+ CurHasPreviousCapture |= IsCaptureUsed;
+ PrevCaptureLoc = CaptureRange.getEnd();
}
// Handle 'this' capture.
if (From.isThisCapture()) {
+ // Capturing 'this' implicitly with a default of '[=]' is deprecated,
+ // because it results in a reference capture. Don't warn prior to
+ // C++2a; there's nothing that can be done about it before then.
+ if (getLangOpts().CPlusPlus2a && IsImplicit &&
+ CaptureDefault == LCD_ByCopy) {
+ Diag(From.getLocation(), diag::warn_deprecated_this_capture);
+ Diag(CaptureDefaultLoc, diag::note_deprecated_this_capture)
+ << FixItHint::CreateInsertion(
+ getLocForEndOfToken(CaptureDefaultLoc), ", this");
+ }
+
Captures.push_back(
LambdaCapture(From.getLocation(), IsImplicit,
From.isCopyCapture() ? LCK_StarThis : LCK_This));
@@ -1583,19 +1646,19 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
// FIXME: Fix generic lambda to block conversions.
if (getLangOpts().Blocks && getLangOpts().ObjC1 && !IsGenericLambda)
addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator);
-
+
// Finalize the lambda class.
SmallVector<Decl*, 4> Fields(Class->fields());
ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(),
- SourceLocation(), nullptr);
+ SourceLocation(), ParsedAttributesView());
CheckCompletedCXXClass(Class);
}
Cleanup.mergeFrom(LambdaCleanup);
- LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
+ LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
CaptureDefault, CaptureDefaultLoc,
- Captures,
+ Captures,
ExplicitParams, ExplicitResultType,
CaptureInits, EndLoc,
ContainsUnexpandedParameterPack);
@@ -1655,7 +1718,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
Expr *Src) {
// Make sure that the lambda call operator is marked used.
CXXRecordDecl *Lambda = Conv->getParent();
- CXXMethodDecl *CallOperator
+ CXXMethodDecl *CallOperator
= cast<CXXMethodDecl>(
Lambda->lookup(
Context.DeclarationNames.getCXXOperatorName(OO_Call)).front());
@@ -1668,10 +1731,10 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
CurrentLocation, Src);
if (!Init.isInvalid())
Init = ActOnFinishFullExpr(Init.get());
-
+
if (Init.isInvalid())
return ExprError();
-
+
// Create the new block to be returned.
BlockDecl *Block = BlockDecl::Create(Context, CurContext, ConvLocation);