/// \brief C++11 deduced auto type.
QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto,
- bool IsDependent, bool IsParameterPack) const;
+ bool IsDependent = false) const;
/// \brief C++11 deduction pattern for 'auto' type.
QualType getAutoDeductType() const;
LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent)
: DefinitionData(D), Dependent(Dependent), NumCaptures(0),
- NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0),
- Captures(0), MethodTyInfo(Info), TheLambdaExpr(0)
+ NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0),
+ MethodTyInfo(Info)
{
IsLambda = true;
}
/// within the default argument of a function template, because the
/// lambda will have been created with the enclosing context as its
/// declaration context, rather than function. This is an unfortunate
- /// artifact of having to parse the default arguments before.
+ /// artifact of having to parse the default arguments before
unsigned Dependent : 1;
/// \brief The number of captures in this lambda.
/// \brief The type of the call method.
TypeSourceInfo *MethodTyInfo;
-
- /// \brief The AST node of the lambda expression.
- LambdaExpr *TheLambdaExpr;
-
};
struct DefinitionData &data() {
/// \brief Determine whether this class describes a lambda function object.
bool isLambda() const { return hasDefinition() && data().IsLambda; }
- /// \brief Determine whether this class describes a generic
- /// lambda function object (i.e. function call operator is
- /// a template).
- bool isGenericLambda() const;
-
- /// \brief Retrieve the lambda call operator of the closure type
- /// if this is a closure type.
- CXXMethodDecl* getLambdaCallOperator() const;
-
- /// \brief Retrieve the lambda static invoker, the address of which
- /// is returned by the conversion operator, and the body of which
- /// is forwarded to the lambda call operator.
- CXXMethodDecl* getLambdaStaticInvoker() const;
-
- /// \brief Retrieve the generic lambda's template parameter list.
- /// Returns null if the class does not represent a lambda or a generic
- /// lambda.
- TemplateParameterList* getGenericLambdaTemplateParameterList() const;
-
- /// \brief Assign the member call operator of the lambda.
- void setLambdaExpr(LambdaExpr *E) {
- getLambdaData().TheLambdaExpr = E;
- }
-
- /// \brief Retrieve the parent lambda expression.
- LambdaExpr* getLambdaExpr() const {
- return isLambda() ? getLambdaData().TheLambdaExpr : 0;
- }
-
-
/// \brief For a closure type, retrieve the mapping from captured
/// variables and \c this to the non-static data members that store the
/// values or references of the captures.
/// lambda expression.
CXXMethodDecl *getCallOperator() const;
- /// \brief If this is a generic lambda expression, retrieve the template
- /// parameter list associated with it, or else return null.
- TemplateParameterList *getTemplateParameterList() const;
-
- /// \brief Whether this is a generic lambda.
- bool isGenericLambda() const { return !!getTemplateParameterList(); }
-
/// \brief Retrieve the body of the lambda.
CompoundStmt *getBody() const;
/// is no deduced type and an auto type is canonical. In the latter case, it is
/// also a dependent type.
class AutoType : public Type, public llvm::FoldingSetNode {
- AutoType(QualType DeducedType, bool IsDecltypeAuto,
- bool IsDependent, bool IsParameterPack)
+ AutoType(QualType DeducedType, bool IsDecltypeAuto, bool IsDependent)
: Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
/*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
- /*VariablyModified=*/false, /*ContainsParameterPack=*/IsParameterPack) {
+ /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
assert((DeducedType.isNull() || !IsDependent) &&
"auto deduced to dependent type");
AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto;
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getDeducedType(), isDecltypeAuto(),
- isDependentType(), containsUnexpandedParameterPack());
+ Profile(ID, getDeducedType(), isDecltypeAuto(), isDependentType());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,
- bool IsDecltypeAuto, bool IsDependent,
- bool IsParameterPack) {
+ bool IsDecltypeAuto, bool IsDependent) {
ID.AddPointer(Deduced.getAsOpaquePtr());
ID.AddBoolean(IsDecltypeAuto);
ID.AddBoolean(IsDependent);
- ID.AddBoolean(IsParameterPack);
}
static bool classof(const Type *T) {
"cannot deduce type for lambda capture %0 from initializer list">;
}
-// C++1y Generic Lambdas
-def err_glambda_not_fully_implemented : Error<
- "unimplemented generic lambda feature: %0">;
-
def err_return_in_captured_stmt : Error<
"cannot return from %0">;
def err_capture_block_variable : Error<
ObjCCatchContext, // Objective-C catch exception-declaration
BlockLiteralContext, // Block literal declarator.
LambdaExprContext, // Lambda-expression declarator.
- LambdaExprParameterContext, // Lambda-expression parameter declarator.
ConversionIdContext, // C++ conversion-type-id.
TrailingReturnContext, // C++11 trailing-type-specifier.
TemplateTypeArgContext, // Template type argument.
~Declarator() {
clear();
}
+
/// getDeclSpec - Return the declaration-specifier that this declarator was
/// declared with.
const DeclSpec &getDeclSpec() const { return DS; }
bool isPrototypeContext() const {
return (Context == PrototypeContext ||
Context == ObjCParameterContext ||
- Context == ObjCResultContext ||
- Context == LambdaExprParameterContext);
+ Context == ObjCResultContext);
}
/// \brief Get the source range that spans this declarator.
case AliasDeclContext:
case AliasTemplateContext:
case PrototypeContext:
- case LambdaExprParameterContext:
case ObjCParameterContext:
case ObjCResultContext:
case TemplateParamContext:
case ForContext:
case ConditionContext:
case PrototypeContext:
- case LambdaExprParameterContext:
case TemplateParamContext:
case CXXCatchContext:
case ObjCCatchContext:
case ForContext:
case ConditionContext:
case PrototypeContext:
- case LambdaExprParameterContext:
case TemplateParamContext:
case CXXCatchContext:
case ObjCCatchContext:
case KNRTypeListContext:
case MemberContext:
case PrototypeContext:
- case LambdaExprParameterContext:
case ObjCParameterContext:
case ObjCResultContext:
case TemplateParamContext:
case AliasDeclContext:
case AliasTemplateContext:
case PrototypeContext:
- case LambdaExprParameterContext:
case ObjCParameterContext:
case ObjCResultContext:
case TemplateParamContext:
class ReturnStmt;
class Scope;
class SwitchStmt;
-class TemplateTypeParmDecl;
-class TemplateParameterList;
class VarDecl;
class DeclRefExpr;
class ObjCIvarRefExpr;
/// \brief Offsets into the ArrayIndexVars array at which each capture starts
/// its list of array index variables.
SmallVector<unsigned, 4> ArrayIndexStarts;
-
- /// \brief If this is a generic lambda, use this as the depth of
- /// each 'auto' parameter, during initial AST construction.
- unsigned AutoTemplateParameterDepth;
-
- // If this is a generic lambda, store the list of the auto
- // parameters converted into TemplateTypeParmDecls into a vector
- // that can be used to construct the generic lambda's template
- // parameter list, during initial AST construction.
- /// \brief Store the list of the auto parameters for a generic lambda.
- SmallVector<TemplateTypeParmDecl*, 4> AutoTemplateParams;
-
- // If this is a generic lambda, store its template parameter list.
- TemplateParameterList *GLTemplateParameterList;
-
- LambdaScopeInfo(DiagnosticsEngine &Diag)
- : CapturingScopeInfo(Diag, ImpCap_None), Lambda(0),
- CallOperator(0), NumExplicitCaptures(0), Mutable(false),
- ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false),
- AutoTemplateParameterDepth(0),
- GLTemplateParameterList(0)
+
+ LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
+ CXXMethodDecl *CallOperator)
+ : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
+ CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false),
+ ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false)
{
Kind = SK_Lambda;
}
}
static bool classof(const FunctionScopeInfo *FSI) {
- return FSI->Kind == SK_Lambda;
+ return FSI->Kind == SK_Lambda;
}
-
-
};
void PushFunctionScope();
void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
- void PushLambdaScope();
-
- // This is used to inform Sema what the current TemplateParameterDepth
- // is during Parsing. Currently it is used to pass on the depth
- // when parsing generic lambda 'auto' parameters.
- void RecordParsingTemplateParameterDepth(unsigned Depth);
-
+ void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator);
void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
RecordDecl *RD,
CapturedRegionKind K);
/// \brief Retrieve the current block, if any.
sema::BlockScopeInfo *getCurBlock();
- /// \brief Retrieve the current lambda scope info, if any.
+ /// \brief Retrieve the current lambda expression, if any.
sema::LambdaScopeInfo *getCurLambda();
- /// \brief Retrieve the current generic lambda info, if any.
- sema::LambdaScopeInfo *getCurGenericLambda();
-
/// \brief Retrieve the current captured region, if any.
sema::CapturedRegionScopeInfo *getCurCapturedRegion();
/// initializer for the declaration 'Dcl'.
void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
- /// \brief Invoked when an auto parameter is parsed
- /// in a lambda's parameter declaration clause.
- ParmVarDecl *ActOnLambdaAutoParameter(ParmVarDecl *P);
-
/// \brief Create a new lambda closure type.
CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
SourceLocation EndLoc,
ArrayRef<ParmVarDecl *> Params);
- /// \brief Endow the lambda scope info with the relevant properties.
- void buildLambdaScope(sema::LambdaScopeInfo *LSI,
- CXXMethodDecl *CallOperator,
- SourceRange IntroducerRange,
- LambdaCaptureDefault CaptureDefault,
- SourceLocation CaptureDefaultLoc,
- bool ExplicitParams,
- bool ExplicitResultType,
- bool Mutable);
+ /// \brief Introduce the scope for a lambda expression.
+ sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
+ SourceRange IntroducerRange,
+ LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
+ bool ExplicitParams,
+ bool ExplicitResultType,
+ bool Mutable);
/// \brief Check and build an init-capture with the specified name and
/// initializer.
sema::TemplateDeductionInfo &Info,
bool InOverloadResolution = false);
- /// \brief Substitute Replacement for \p auto in \p TypeWithAuto
- QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
- /// \brief Substitute Replacement for auto in TypeWithAuto
- TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
- QualType Replacement);
-
/// \brief Result type of DeduceAutoType.
enum DeduceAutoResult {
DAR_Succeeded,
QualType &Result);
DeduceAutoResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer,
QualType &Result);
+ QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose = true);
+++ /dev/null
-//===--- SemaLambda.h - Lambda Helper Functions --------------*- C++ -*-===//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-///\r
-/// \file\r
-/// \brief This file provides some common utility functions for processing\r
-/// Lambdas.\r
-///\r
-//===----------------------------------------------------------------------===//\r
-\r
-#ifndef LLVM_CLANG_SEMA_LAMBDA_H\r
-#define LLVM_CLANG_SEMA_LAMBDA_H\r
-\r
-#include "clang/AST/DeclCXX.h"\r
-#include "clang/AST/DeclTemplate.h"\r
-#include "clang/Sema/ScopeInfo.h"\r
-\r
-namespace clang {\r
-static inline const char *getLambdaStaticInvokerName() {\r
- return "__invoke";\r
-}\r
-static inline bool isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) {\r
- if (MD) {\r
- CXXRecordDecl *LambdaClass = MD->getParent();\r
- if (LambdaClass && LambdaClass->isGenericLambda()) {\r
- return LambdaClass->getLambdaCallOperator() \r
- == MD->getTemplateInstantiationPattern();\r
- }\r
- }\r
- return false;\r
-}\r
-\r
-static inline bool isGenericLambdaCallOperatorSpecialization(Decl *D) {\r
- return isGenericLambdaCallOperatorSpecialization(\r
- dyn_cast<CXXMethodDecl>(D));\r
-}\r
-} // clang\r
-\r
-#endif // LLVM_CLANG_SEMA_LAMBDA_H\r
/// deduced to the given type, or to the canonical undeduced 'auto' type, or the
/// canonical deduced-but-dependent 'auto' type.
QualType ASTContext::getAutoType(QualType DeducedType, bool IsDecltypeAuto,
- bool IsDependent, bool IsParameterPack) const {
- if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent &&
- !IsParameterPack)
+ bool IsDependent) const {
+ if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent)
return getAutoDeductType();
- assert(!IsParameterPack || DeducedType.isNull()
- && "Auto parameter pack: auto ... a should always be undeduced!");
+
// Look in the folding set for an existing type.
void *InsertPos = 0;
llvm::FoldingSetNodeID ID;
- AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent,
- IsParameterPack);
+ AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent);
if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(AT, 0);
AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType,
IsDecltypeAuto,
- IsDependent,
- IsParameterPack);
+ IsDependent);
Types.push_back(AT);
if (InsertPos)
AutoTypes.InsertNode(AT, InsertPos);
if (AutoDeductTy.isNull())
AutoDeductTy = QualType(
new (*this, TypeAlignment) AutoType(QualType(), /*decltype(auto)*/false,
- /*dependent*/false,
- /*IsParameterPack*/false),
+ /*dependent*/false),
0);
return AutoDeductTy;
}
return QualType();
}
- return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto(),
- /*IsDependent*/false,
- T->containsUnexpandedParameterPack());
+ return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto());
}
QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/IdentifierTable.h"
-#include "clang/Sema/SemaLambda.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace clang;
return isPOD() && data().HasOnlyCMembers;
}
-bool CXXRecordDecl::isGenericLambda() const {
- return isLambda() &&
- getLambdaCallOperator()->getDescribedFunctionTemplate();
-}
-
-CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
- if (!isLambda()) return 0;
- DeclarationName Name = \r
- getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);\r
- DeclContext::lookup_const_result Calls = lookup(Name);
-\r
- assert(!Calls.empty() && "Missing lambda call operator!");\r
- assert(Calls.size() == 1 && "More than one lambda call operator!"); \r
- \r
- NamedDecl *CallOp = Calls.front();\r
- if (FunctionTemplateDecl *CallOpTmpl = \r
- dyn_cast<FunctionTemplateDecl>(CallOp)) \r
- return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl());\r
-
- return cast<CXXMethodDecl>(CallOp);
-}
-
-CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
- if (!isLambda()) return 0;
- DeclarationName Name = \r
- &getASTContext().Idents.get(getLambdaStaticInvokerName());\r
- DeclContext::lookup_const_result Invoker = lookup(Name);
- if (Invoker.empty()) return 0;\r
- assert(Invoker.size() == 1 && "More than one static invoker operator!"); \r
- CXXMethodDecl *Result = cast<CXXMethodDecl>(Invoker.front()); \r
- return Result;
-
-}
-
void CXXRecordDecl::getCaptureFields(
llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
FieldDecl *&ThisCapture) const {
}
}
-TemplateParameterList*
- CXXRecordDecl::getGenericLambdaTemplateParameterList() const {
- if (!isLambda()) return 0;
- CXXMethodDecl *CallOp = getLambdaCallOperator();
- if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate())
- return Tmpl->getTemplateParameters();
- return 0;
-}
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
QualType T;
bool CXXMethodDecl::isLambdaStaticInvoker() const {
return getParent()->isLambda() &&
- getParent()->getLambdaStaticInvoker() == this;
+ getIdentifier() && getIdentifier()->getName() == "__invoke";
}
CXXMethodDecl *LambdaExpr::getCallOperator() const {
CXXRecordDecl *Record = getLambdaClass();
- return Record->getLambdaCallOperator();
-}
-
-TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
- CXXRecordDecl *Record = getLambdaClass();
- return Record->getGenericLambdaTemplateParameterList();
-
+ DeclarationName Name
+ = Record->getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
+ DeclContext::lookup_result Calls = Record->lookup(Name);
+ assert(!Calls.empty() && "Missing lambda call operator!");
+ assert(Calls.size() == 1 && "More than one lambda call operator!");
+ CXXMethodDecl *Result = cast<CXXMethodDecl>(Calls.front());
+ return Result;
}
CompoundStmt *LambdaExpr::getBody() const {
AutoType *VisitAttributedType(const AttributedType *T) {
return Visit(T->getModifiedType());
}
- AutoType *VisitPackExpansionType(const PackExpansionType *T) {
- return Visit(T->getPattern());
- }
-
};
}
EmitLambdaToBlockPointerBody(Args);
} else if (isa<CXXMethodDecl>(FD) &&
cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {
- // The lambda static invoker function is special, because it forwards or
+ // The lambda "__invoke" function is special, because it forwards or
// clones the body of the function call operator (but is actually static).
EmitLambdaStaticInvokeFunction(cast<CXXMethodDecl>(FD));
} else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) &&
// as part of the parameter-declaration-clause.
if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
!((D.getContext() == Declarator::PrototypeContext ||
- D.getContext() == Declarator::LambdaExprParameterContext ||
D.getContext() == Declarator::BlockLiteralContext) &&
NextToken().is(tok::r_paren) &&
!D.hasGroupingParens() &&
TypeResult TrailingReturnType;
Actions.ActOnStartFunctionDeclarator();
+
/* LocalEndLoc is the end location for the local FunctionTypeLoc.
EndLoc is the end location for the function declarator.
They differ for trailing return types. */
EndLoc = RParenLoc;
} else {
if (Tok.isNot(tok::r_paren))
- ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo,
- EllipsisLoc);
+ ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc);
else if (RequiresArg)
Diag(Tok, diag::err_argument_required_after_attribute);
ParsedAttributes &FirstArgAttrs,
SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
SourceLocation &EllipsisLoc) {
+
while (1) {
if (Tok.is(tok::ellipsis)) {
// FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
ParseDeclarationSpecifiers(DS);
-
- // Parse the declarator. This is "PrototypeContext" or
- // "LambdaExprParameterContext", because we must accept either
- // 'declarator' or 'abstract-declarator' here.
- Declarator ParmDeclarator(DS,
- D.getContext() == Declarator::LambdaExprContext ?
- Declarator::LambdaExprParameterContext :
- Declarator::PrototypeContext);
- ParseDeclarator(ParmDeclarator);
+ // Parse the declarator. This is "PrototypeContext", because we must
+ // accept either 'declarator' or 'abstract-declarator' here.
+ Declarator ParmDecl(DS, Declarator::PrototypeContext);
+ ParseDeclarator(ParmDecl);
// Parse GNU attributes, if present.
- MaybeParseGNUAttributes(ParmDeclarator);
+ MaybeParseGNUAttributes(ParmDecl);
// Remember this parsed parameter in ParamInfo.
- IdentifierInfo *ParmII = ParmDeclarator.getIdentifier();
+ IdentifierInfo *ParmII = ParmDecl.getIdentifier();
// DefArgToks is used when the parsing of default arguments needs
// to be delayed.
// If no parameter was specified, verify that *something* was specified,
// otherwise we have a missing type and identifier.
- if (DS.isEmpty() && ParmDeclarator.getIdentifier() == 0 &&
- ParmDeclarator.getNumTypeObjects() == 0) {
+ if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 &&
+ ParmDecl.getNumTypeObjects() == 0) {
// Completely missing, emit error.
Diag(DSStart, diag::err_missing_param);
} else {
// Inform the actions module about the parameter declarator, so it gets
// added to the current scope.
- Decl *Param = Actions.ActOnParamDeclarator(getCurScope(),
- ParmDeclarator);
+ Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
+
// Parse the default argument, if any. We parse the default
// arguments in all dialects; the semantic analysis in
// ActOnParamDefaultArgument will reject the default argument in
}
ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
- ParmDeclarator.getIdentifierLoc(),
- Param, DefArgToks));
+ ParmDecl.getIdentifierLoc(), Param,
+ DefArgToks));
}
// If the next token is a comma, consume it and keep reading arguments.
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "llvm/Support/ErrorHandling.h"
-#include "clang/AST/DeclTemplate.h"
using namespace clang;
PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
"lambda expression parsing");
-
-
// FIXME: Call into Actions to add any init-capture declarations to the
// scope while parsing the lambda-declarator and compound-statement.
// Parse lambda-declarator[opt].
DeclSpec DS(AttrFactory);
Declarator D(DS, Declarator::LambdaExprContext);
- TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
- Actions.PushLambdaScope();
if (Tok.is(tok::l_paren)) {
ParseScope PrototypeScope(this,
SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
SourceLocation EllipsisLoc;
-
- if (Tok.isNot(tok::r_paren)) {
- sema::LambdaScopeInfo *LSI = Actions.getCurLambda();
- if (getLangOpts().CPlusPlus1y)
- Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
+ if (Tok.isNot(tok::r_paren))
ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc);
- // For a generic lambda, each 'auto' within the parameter declaration
- // clause creates a template type parameter, so increment the depth.
- if (getLangOpts().CPlusPlus1y && Actions.getCurGenericLambda())
- ++CurTemplateDepthTracker;
- }
+
T.consumeClose();
SourceLocation RParenLoc = T.getCloseLocation();
DeclEndLoc = RParenLoc;
// Ask the actions module to compute the type for this declarator.
Decl *Param =
Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator);
+
if (Param &&
// A missing identifier has already been diagnosed.
ParmDeclarator.getIdentifier()) {
BlockScope, Block));
}
-void Sema::PushLambdaScope() {
- FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics()));
-}
-
-void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
- if (LambdaScopeInfo *const LSI = getCurLambda()) {
- LSI->AutoTemplateParameterDepth = Depth;
- return;
- }
- assert(false &&
- "Remove assertion if intentionally called in a non-lambda context.");
+void Sema::PushLambdaScope(CXXRecordDecl *Lambda,
+ CXXMethodDecl *CallOperator) {
+ FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda,
+ CallOperator));
}
void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
}
-// We have a generic lambda if we parsed auto parameters, or we have
-// an associated template parameter list.
-LambdaScopeInfo *Sema::getCurGenericLambda() {
- if (LambdaScopeInfo *LSI = getCurLambda()) {
- return (LSI->AutoTemplateParams.size() ||
- LSI->GLTemplateParameterList) ? LSI : 0;
- }
- return 0;
-}
-
void Sema::ActOnComment(SourceRange Comment) {
if (!LangOpts.RetainCommentsFromSystemHeaders &&
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Initialization.h"
-#include "clang/Sema/SemaLambda.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
const DeclSpec &DS = D.getDeclSpec();
// Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
-
// C++03 [dcl.stc]p2 also permits 'auto'.
VarDecl::StorageClass StorageClass = SC_None;
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
if (New->hasAttr<BlocksAttr>()) {
Diag(New->getLocation(), diag::err_block_on_nonlocal);
}
-
- // Handle 'auto' within a generic lambda.
- QualType ParamType = New->getType();
- if (getLangOpts().CPlusPlus1y && ParamType->getContainedAutoType()) {
- assert(getCurLambda() &&
- "'auto' in parameter type only allowed in lambdas!");
- New = ActOnLambdaAutoParameter(New);
- }
return New;
}
FD = FunTmpl->getTemplatedDecl();
else
FD = cast<FunctionDecl>(D);
- // If we are instantiating a generic lambda call operator, push
- // a LambdaScopeInfo onto the function stack. But use the information
- // that's already been calculated (ActOnLambdaExpr) when analyzing the
- // template version, to prime the current LambdaScopeInfo.
- if (getLangOpts().CPlusPlus1y
- && isGenericLambdaCallOperatorSpecialization(D)) {
- CXXMethodDecl *CallOperator = cast<CXXMethodDecl>(D);
- CXXRecordDecl *LambdaClass = CallOperator->getParent();
- LambdaExpr *LE = LambdaClass->getLambdaExpr();
- assert(LE &&
- "No LambdaExpr of closure class when instantiating a generic lambda!");
- assert(ActiveTemplateInstantiations.size() &&
- "There should be an active template instantiation on the stack "
- "when instantiating a generic lambda!");
- PushLambdaScope();
- LambdaScopeInfo *LSI = getCurLambda();
- LSI->CallOperator = CallOperator;
- LSI->Lambda = LambdaClass;
- LSI->ReturnType = CallOperator->getResultType();
-
- if (LE->getCaptureDefault() == LCD_None)
- LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
- else if (LE->getCaptureDefault() == LCD_ByCopy)
- LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
- else if (LE->getCaptureDefault() == LCD_ByRef)
- LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
-
- LSI->IntroducerRange = LE->getIntroducerRange();
- }
- else
- // Enter a new function scope
- PushFunctionScope();
+
+ // Enter a new function scope
+ PushFunctionScope();
// See if this is a redefinition.
if (!FD->isLateTemplateParsed())
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
-#include "clang/Sema/SemaLambda.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
SourceLocation CurrentLocation,
CXXConversionDecl *Conv)
{
- CXXRecordDecl *LambdaClass = Conv->getParent();
+ CXXRecordDecl *Lambda = Conv->getParent();
// Make sure that the lambda call operator is marked used.
- markLambdaCallOperatorUsed(*this, LambdaClass);
+ markLambdaCallOperatorUsed(*this, Lambda);
Conv->setUsed();
SynthesizedFunctionScope Scope(*this, Conv);
DiagnosticErrorTrap Trap(Diags);
- CXXMethodDecl *Invoke = LambdaClass->getLambdaStaticInvoker();
-
+ // Return the address of the __invoke function.
+ DeclarationName InvokeName = &Context.Idents.get("__invoke");
+ CXXMethodDecl *Invoke
+ = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front());
Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(),
VK_LValue, Conv->getLocation()).take();
- assert(FunctionRef && "Can't refer to lambda static invoker function?");
+ assert(FunctionRef && "Can't refer to __invoke function?");
Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
Conv->setBody(new (Context) CompoundStmt(Context, Return,
Conv->getLocation(),
Conv->getLocation()));
- // Fill in the invoke function with a dummy implementation. IR generation
+ // Fill in the __invoke function with a dummy implementation. IR generation
// will fill in the actual details.
Invoke->setUsed();
Invoke->setReferenced();
#include "clang/AST/ExprCXX.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
-#include "clang/Sema/SemaLambda.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
llvm_unreachable("unexpected context");
}
-
-ParmVarDecl *Sema::ActOnLambdaAutoParameter(ParmVarDecl *PVD) {
- LambdaScopeInfo *LSI = getCurLambda();
- assert(LSI && "No LambdaScopeInfo on the stack!");
- const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
- const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
- // Invent a template type parameter corresponding to the auto
- // containing parameter.
- TemplateTypeParmDecl *TemplateParam =
- TemplateTypeParmDecl::Create(Context,
- // Temporarily add to the TranslationUnit DeclContext. When the
- // associated TemplateParameterList is attached to a template
- // declaration (such as FunctionTemplateDecl), the DeclContext
- // for each template parameter gets updated appropriately via
- // a call to AdoptTemplateParameterList.
- Context.getTranslationUnitDecl(),
- SourceLocation(),
- PVD->getLocation(),
- TemplateParameterDepth,
- AutoParameterPosition, // our template param index
- /* Identifier*/ 0, false, PVD->isParameterPack());
- LSI->AutoTemplateParams.push_back(TemplateParam);
- QualType AutoTy = PVD->getType();
- // Now replace the 'auto' in the function parameter with this invented
- // template type parameter.
- QualType TemplParamType = QualType(TemplateParam->getTypeForDecl(), 0);
-
- TypeSourceInfo *AutoTSI = PVD->getTypeSourceInfo();
- TypeSourceInfo *NewTSI = SubstAutoTypeSourceInfo(AutoTSI, TemplParamType);
- PVD->setType(NewTSI->getType());
- PVD->setTypeSourceInfo(NewTSI);
- return PVD;
-}
-
-
-static inline TemplateParameterList *
- getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI,
- Sema &SemaRef) {
- if (LSI->GLTemplateParameterList)
- return LSI->GLTemplateParameterList;
- else if (LSI->AutoTemplateParams.size()) {
- SourceRange IntroRange = LSI->IntroducerRange;
- SourceLocation LAngleLoc = IntroRange.getBegin();
- SourceLocation RAngleLoc = IntroRange.getEnd();
- LSI->GLTemplateParameterList =
- TemplateParameterList::Create(SemaRef.Context,
- /* Template kw loc */ SourceLocation(),
- LAngleLoc,
- (NamedDecl**)LSI->AutoTemplateParams.data(),
- LSI->AutoTemplateParams.size(), RAngleLoc);
- }
- return LSI->GLTemplateParameterList;
-}
-
-
-
CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
SourceRange IntroducerRange,
TypeSourceInfo *MethodType,
SourceLocation EndLoc,
ArrayRef<ParmVarDecl *> Params) {
- TemplateParameterList *TemplateParams =
- getGenericLambdaTemplateParameterList(getCurLambda(), *this);
// C++11 [expr.prim.lambda]p5:
// 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
// Temporarily set the lexical declaration context to the current
// context, so that the Scope stack matches the lexical nesting.
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,
- TemplateParams,
- Method) : 0;
- if (TemplateMethod) {
- TemplateMethod->setLexicalDeclContext(CurContext);
- TemplateMethod->setAccess(AS_public);
- Method->setDescribedFunctionTemplate(TemplateMethod);
- }
// Add parameters.
if (!Params.empty()) {
return Method;
}
-void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
- CXXMethodDecl *CallOperator,
+LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc,
bool ExplicitParams,
bool ExplicitResultType,
bool Mutable) {
- LSI->CallOperator = CallOperator;
- LSI->Lambda = CallOperator->getParent();
+ PushLambdaScope(CallOperator->getParent(), CallOperator);
+ LambdaScopeInfo *LSI = getCurLambda();
if (CaptureDefault == LCD_ByCopy)
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
else if (CaptureDefault == LCD_ByRef)
} else {
LSI->HasImplicitReturnType = true;
}
+
+ return LSI;
}
void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
}
void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
- assert(CSI.HasImplicitReturnType || CSI.ReturnType->isUndeducedType());
+ assert(CSI.HasImplicitReturnType);
// C++ Core Issue #975, proposed resolution:
// If a lambda-expression does not include a trailing-return-type,
// Second case: at least one return statement has dependent type.
// Delay type checking until instantiation.
assert(!CSI.ReturnType.isNull() && "We should have a tentative return type.");
- if (CSI.ReturnType->isDependentType() || CSI.ReturnType->isUndeducedType())
+ if (CSI.ReturnType->isDependentType())
return;
// Try to apply the enum-fuzz rule.
}
void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
- Declarator &ParamInfo, Scope *CurScope) {
+ Declarator &ParamInfo,
+ Scope *CurScope) {
// Determine if we're within a context where we know that the lambda will
// be dependent, because there are template parameters in scope.
bool KnownDependent = false;
- LambdaScopeInfo *const LSI = getCurLambda();
- assert(LSI && "LambdaScopeInfo should be on stack!");
- TemplateParameterList *TemplateParams =
- getGenericLambdaTemplateParameterList(LSI, *this);
-
- if (Scope *TmplScope = CurScope->getTemplateParamParent()) {
- // Since we have our own TemplateParams, so check if an outer scope
- // has template params, only then are we in a dependent scope.
- if (TemplateParams) {
- TmplScope = TmplScope->getParent();
- TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : 0;
- }
- if (TmplScope && !TmplScope->decl_empty())
+ if (Scope *TmplScope = CurScope->getTemplateParamParent())
+ if (!TmplScope->decl_empty())
KnownDependent = true;
- }
+
// Determine the signature of the call operator.
TypeSourceInfo *MethodTyInfo;
bool ExplicitParams = true;
FunctionProtoType::ExtProtoInfo EPI;
EPI.HasTrailingReturn = true;
EPI.TypeQuals |= DeclSpec::TQ_const;
- // For C++1y, use the new return type deduction machinery, by imaginging
- // 'auto' if no trailing return type.
- QualType DefaultTypeForNoTrailingReturn = getLangOpts().CPlusPlus1y ?
- Context.getAutoDeductType() : Context.DependentTy;
- QualType MethodTy = Context.getFunctionType(DefaultTypeForNoTrailingReturn, None,
+ QualType MethodTy = Context.getFunctionType(Context.DependentTy, None,
EPI);
MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
ExplicitParams = false;
if (!FTI.hasMutableQualifier())
FTI.TypeQuals |= DeclSpec::TQ_const;
- ExplicitResultType = FTI.hasTrailingReturnType();
- // In C++11 if there is no explicit return type, the return type is
- // artificially set to DependentTy, whereas in C++1y it is set to AutoTy
- // (through ConvertDeclSpecToType) which allows us to support both
- // C++11 and C++1y return type deduction semantics.
MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
assert(MethodTyInfo && "no type from lambda-declarator");
EndLoc = ParamInfo.getSourceRange().getEnd();
+ ExplicitResultType
+ = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType()
+ != Context.DependentTy;
+
if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
// Empty arg list, don't push any params.
CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
MethodTyInfo, EndLoc, Params);
+
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
// Introduce the function call operator as the current declaration context.
PushDeclContext(CurScope, Method);
- // Build the lambda scope.
- buildLambdaScope(LSI, Method,
+ // Introduce the lambda scope.
+ LambdaScopeInfo *LSI
+ = enterLambdaScope(Method,
Intro.Range,
Intro.Default, Intro.DefaultLoc,
ExplicitParams,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
- // FIXME: The conversion operator needs to be fixed for generic lambdas.
- if (Class->isGenericLambda()) return;
// Add the conversion to function pointer.
const FunctionProtoType *Proto
= CallOperator->getType()->getAs<FunctionProtoType>();
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
Class->addDecl(Conversion);
- // Add a non-static member function that will be the result of
- // the conversion with a certain unique ID.
- Name = &S.Context.Idents.get(getLambdaStaticInvokerName());
+
+ // Add a non-static member function "__invoke" that will be the result of
+ // the conversion.
+ Name = &S.Context.Idents.get("__invoke");
CXXMethodDecl *Invoke
= CXXMethodDecl::Create(S.Context, Class, Loc,
DeclarationNameInfo(Name, Loc), FunctionTy,
// If a lambda-expression does not include a
// trailing-return-type, it is as if the trailing-return-type
// denotes the following type:
- // Skip for C++1y return type deduction semantics which uses
- // different machinery currently.
- // FIXME: Refactor and Merge the return type deduction machinery.
// FIXME: Assumes current resolution to core issue 975.
- if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus1y) {
+ if (LSI->HasImplicitReturnType) {
deduceClosureReturnType(*LSI);
// - if there are no return statements in the
LSI->ReturnType, Proto->getArgTypes(), Proto->getExtProtoInfo());
CallOperator->setType(FunctionTy);
}
+
// C++ [expr.prim.lambda]p7:
// The lambda-expression's compound-statement yields the
// function-body (8.4) of the function call operator [...].
ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation);
CallOperator->setLexicalDeclContext(Class);
- Decl *TemplateOrNonTemplateCallOperatorDecl =
- !CallOperator->getDescribedFunctionTemplate() ? cast<Decl>(CallOperator)
- : CallOperator->getDescribedFunctionTemplate();
-
- TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);
- Class->addDecl(TemplateOrNonTemplateCallOperatorDecl);
-
+ Class->addDecl(CallOperator);
PopExpressionEvaluationContext();
// C++11 [expr.prim.lambda]p6:
CaptureInits, ArrayIndexVars,
ArrayIndexStarts, Body->getLocEnd(),
ContainsUnexpandedParameterPack);
- Class->setLambdaExpr(Lambda);
+
// C++11 [expr.prim.lambda]p2:
// A lambda-expression shall not appear in an unevaluated operand
// (Clause 5).
break;
}
}
- // TODO: Implement capturing.
- if (Lambda->isGenericLambda()) {
- if (Lambda->getCaptureDefault() != LCD_None) {
- Diag(Lambda->getIntroducerRange().getBegin(),
- diag::err_glambda_not_fully_implemented)
- << " capturing not implemented yet";
- return ExprError();
- }
- }
+
return MaybeBindToTemporary(Lambda);
}
}
}
}
- // FIXME: For generic lambda parameters, check if the function is a lambda
- // call operator, and if so, emit a prettier and more informative
- // diagnostic that mentions 'auto' and lambda in addition to
- // (or instead of?) the canonical template type parameters.
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_non_deduced_mismatch)
<< FirstTA << SecondTA;
// [expr.prim.lambda]p4 in C++11; block literals follow the same rules.
CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction());
QualType FnRetType = CurCap->ReturnType;
- LambdaScopeInfo *const LambdaSI = getCurLambda();
- // In C++1y, an implicit return type behaves as if 'auto' was
- // the return type.
- if (FnRetType.isNull() && getLangOpts().CPlusPlus1y) {
- if (LambdaSI) {
- FunctionDecl *CallOp = LambdaSI->CallOperator;
- FnRetType = CallOp->getResultType();
- assert(FnRetType->getContainedAutoType());
- }
- }
-
- // For blocks/lambdas with implicit return types in C++11, we check each
- // return statement individually, and deduce the common return type when
- // the block or lambda is completed. In C++1y, the return type deduction
- // of a lambda is specified in terms of auto.
- // Notably, in C++11, we take the type of the expression after decay and
- // lvalue-to-rvalue conversion, so a class type can be cv-qualified.
- // In C++1y, we perform template argument deduction as if the return
- // type were 'auto', so an implicit return type is never cv-qualified.
- // i.e if (getLangOpts().CPlusPlus1y && FnRetType.hasQualifiers())
- // FnRetType = FnRetType.getUnqualifiedType();
- // Return type deduction is unchanged for blocks in C++1y.
- // FIXME: Fold this into the 'auto' codepath below.
- if (CurCap->HasImplicitReturnType &&
- (!LambdaSI || !getLangOpts().CPlusPlus1y)) {
+
+ // For blocks/lambdas with implicit return types, we check each return
+ // statement individually, and deduce the common return type when the block
+ // or lambda is completed.
+ if (CurCap->HasImplicitReturnType) {
+ // FIXME: Fold this into the 'auto' codepath below.
if (RetValExp && !isa<InitListExpr>(RetValExp)) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp);
if (Result.isInvalid())
RetValExp = Result.take();
if (!CurContext->isDependentContext()) {
- FnRetType = RetValExp->getType();
+ FnRetType = RetValExp->getType();
+ // In C++11, we take the type of the expression after decay and
+ // lvalue-to-rvalue conversion, so a class type can be cv-qualified.
+ // In C++1y, we perform template argument deduction as if the return
+ // type were 'auto', so an implicit return type is never cv-qualified.
+ if (getLangOpts().CPlusPlus1y && FnRetType.hasQualifiers())
+ FnRetType = FnRetType.getUnqualifiedType();
} else
FnRetType = CurCap->ReturnType = Context.DependentTy;
} else {
Diag(ReturnLoc, diag::err_lambda_return_init_list)
<< RetValExp->getSourceRange();
}
+
FnRetType = Context.VoidTy;
}
if (CurCap->ReturnType.isNull())
CurCap->ReturnType = FnRetType;
} else if (AutoType *AT =
- (FnRetType.isNull() || !LambdaSI) ? 0
- : FnRetType->getContainedAutoType()) {
+ FnRetType.isNull() ? 0 : FnRetType->getContainedAutoType()) {
// In C++1y, the return type may involve 'auto'.
FunctionDecl *FD = cast<LambdaScopeInfo>(CurCap)->CallOperator;
if (CurContext->isDependentContext()) {
// Return type deduction [...] occurs when the definition is
// instantiated even if the function body contains a return
// statement with a non-type-dependent operand.
- CurCap->ReturnType = FnRetType;
+ CurCap->ReturnType = FnRetType = Context.DependentTy;
} else if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
FD->setInvalidDecl();
return StmtError();
// pickier with blocks than for normal functions because we don't have GCC
// compatibility to worry about here.
const VarDecl *NRVOCandidate = 0;
- if (FnRetType->isDependentType() || FnRetType->isUndeducedType()) {
+ if (FnRetType->isDependentType()) {
// Delay processing for now. TODO: there are lots of dependent
// types we can conclusively prove aren't void.
} else if (FnRetType->isVoidType()) {
return Owned(Result);
}
+
/// Deduce the return type for a function from a returned expression, per
/// C++1y [dcl.spec.auto]p6.
bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
TypeLoc OrigResultType = FD->getTypeSourceInfo()->getTypeLoc().
IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc();
QualType Deduced;
+
if (RetExpr && isa<InitListExpr>(RetExpr)) {
// If the deduction is for a return statement and the initializer is
// a braced-init-list, the program is ill-formed.
AutoType *NewAT = Deduced->getContainedAutoType();
if (!FD->isDependentContext() &&
!Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) {
- LambdaScopeInfo *const LambdaSI = getCurLambda();
- if (LambdaSI && LambdaSI->HasImplicitReturnType) {
- Diag(ReturnLoc,
- diag::err_typecheck_missing_return_type_incompatible)
- << NewAT->getDeducedType() << AT->getDeducedType()
- << true /*IsLambda*/;
- }
- else {
- Diag(ReturnLoc, diag::err_auto_fn_different_deductions)
- << (AT->isDecltypeAuto() ? 1 : 0)
- << NewAT->getDeducedType() << AT->getDeducedType();
- }
+ Diag(ReturnLoc, diag::err_auto_fn_different_deductions)
+ << (AT->isDecltypeAuto() ? 1 : 0)
+ << NewAT->getDeducedType() << AT->getDeducedType();
return true;
}
} else if (!FD->isInvalidDecl()) {
// Check for unexpanded parameter packs.
if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
return StmtError();
+
if (isa<CapturingScopeInfo>(getCurFunction()))
return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp);
+
QualType FnRetType;
QualType RelatedRetType;
if (const FunctionDecl *FD = getCurFunctionDecl()) {
QualType Result =
SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement,
TL.getTypePtr()->isDecltypeAuto(),
- Dependent, TL.getTypePtr()->
- containsUnexpandedParameterPack());
+ Dependent);
AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
return DAR_Succeeded;
}
-QualType Sema::SubstAutoType(QualType TypeWithAuto,
- QualType TypeToReplaceAuto) {
- return SubstituteAutoTransform(*this, TypeToReplaceAuto).
- TransformType(TypeWithAuto);
-}
-
-TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
- QualType TypeToReplaceAuto) {
- return SubstituteAutoTransform(*this, TypeToReplaceAuto).
- TransformType(TypeWithAuto);
+QualType Sema::SubstAutoType(QualType Type, QualType Deduced) {
+ return SubstituteAutoTransform(*this, Deduced).TransformType(Type);
}
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
// specified with a trailing return type or inferred.
if (declarator.getContext() == Declarator::LambdaExprContext ||
isOmittedBlockReturnType(declarator)) {
- // In C++1y (n3690 CD), 5.1.2 [expr.prim.lambda]/4 : The lambda return
- // type is auto, which is replaced by the trailing-return-type if
- // provided and/or deduced from return statements as described
- // in 7.1.6.4.
- Result = S.getLangOpts().CPlusPlus1y &&
- declarator.getContext() == Declarator::LambdaExprContext
- ? Context.getAutoDeductType() : Context.DependentTy;
+ Result = Context.DependentTy;
break;
}
case DeclSpec::TST_auto:
// TypeQuals handled by caller.
- Result = Context.getAutoType(QualType(),
- /*decltype(auto)*/false,
- /*IsDependent*/ false,
- /*IsParameterPack*/ declarator.hasEllipsis());
+ Result = Context.getAutoType(QualType(), /*decltype(auto)*/false);
break;
case DeclSpec::TST_decltype_auto:
- Result = Context.getAutoType(QualType(),
- /*decltype(auto)*/true,
- /*IsDependent*/ false,
- /*IsParameterPack*/ false);
+ Result = Context.getAutoType(QualType(), /*decltype(auto)*/true);
break;
case DeclSpec::TST_unknown_anytype:
ASM = ArrayType::Normal;
}
} else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
- !T->isIncompleteType() && !T->isUndeducedType()) {
+ !T->isIncompleteType()) {
// Is the array too large?
unsigned ActiveSizeBits
= ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
// In C++11, a function declarator using 'auto' must have a trailing return
// type (this is checked later) and we can skip this. In other languages
// using auto, we need to check regardless.
- // Generic Lambdas (C++14) allow 'auto' in their parameters.
if (ContainsPlaceholderType &&
(!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {
int Error = -1;
case Declarator::ObjCParameterContext:
case Declarator::ObjCResultContext:
case Declarator::PrototypeContext:
- Error = 0;
- break;
- case Declarator::LambdaExprParameterContext:
- if (!(SemaRef.getLangOpts().CPlusPlus1y
- && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))
- Error = 0;
+ Error = 0; // Function prototype
break;
case Declarator::MemberContext:
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
AutoRange = D.getName().getSourceRange();
if (Error != -1) {
- if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto) {
- SemaRef.Diag(AutoRange.getBegin(),
- diag::err_decltype_auto_function_declarator_not_declaration);
- } else {
SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
<< Error << AutoRange;
- }
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
} else
D.setInvalidType(true);
break;
case Declarator::PrototypeContext:
- case Declarator::LambdaExprParameterContext:
case Declarator::ObjCParameterContext:
case Declarator::ObjCResultContext:
case Declarator::KNRTypeListContext:
}
}
}
- const AutoType *AT = T->getContainedAutoType();
- // Allow arrays of auto if we are a generic lambda parameter.
- // i.e. [](auto (&array)[5]) { return array[0]; }; OK
- if (AT && !(S.getLangOpts().CPlusPlus1y &&
- D.getContext() == Declarator::LambdaExprParameterContext)) {
+
+ if (const AutoType *AT = T->getContainedAutoType()) {
// We've already diagnosed this for decltype(auto).
if (!AT->isDecltypeAuto())
S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
// is a parameter pack (14.5.3). [...]
switch (D.getContext()) {
case Declarator::PrototypeContext:
- case Declarator::LambdaExprParameterContext:
// C++0x [dcl.fct]p13:
// [...] When it is part of a parameter-declaration-clause, the
// parameter pack is a function parameter pack (14.5.3). The type T
T = Context.getPackExpansionType(T, None);
}
break;
+
case Declarator::TemplateParamContext:
// C++0x [temp.param]p15:
// If a template-parameter is a [...] is a parameter-declaration that
// Note, IsDependent is always false here: we implicitly convert an 'auto'
// which has been deduced to a dependent type into an undeduced 'auto', so
// that we'll retry deduction after the transformation.
- // FIXME: Can we assume the same about IsParameterPack?
- return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto,
- /*IsDependent*/ false,
- /*IsParameterPack*/ false);
+ return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto);
}
/// \brief Build a new template specialization type.
Qs.removeObjCLifetime();
Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(),
Qs);
- Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(),
- AutoTy->isDependentType(),
- AutoTy->containsUnexpandedParameterPack());
+ Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto());
TLB.TypeWasModifiedSafely(Result);
} else {
// Otherwise, complain about the addition of a qualifier to an
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
-
- // FIXME: Implement nested generic lambda transformations.
- if (E->isGenericLambda()) {
- getSema().Diag(E->getIntroducerRange().getBegin(),
- diag::err_glambda_not_fully_implemented)
- << " nested lambdas not implemented yet";
- return ExprError();
- }
// Transform the type of the lambda parameters and start the definition of
// the lambda itself.
TypeSourceInfo *MethodTy
E->getCallOperator()->param_size(),
0, ParamTypes, &Params))
return ExprError();
- getSema().PushLambdaScope();
- LambdaScopeInfo *LSI = getSema().getCurLambda();
- // TODO: Fix for nested lambdas
- LSI->GLTemplateParameterList = 0;
+
// Build the call operator.
CXXMethodDecl *CallOperator
= getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
// Introduce the context of the call operator.
Sema::ContextRAII SavedContext(getSema(), CallOperator);
- LambdaScopeInfo *const LSI = getSema().getCurLambda();
// Enter the scope of the lambda.
- getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(),
+ sema::LambdaScopeInfo *LSI
+ = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(),
E->getCaptureDefault(),
E->getCaptureDefaultLoc(),
E->hasExplicitParameters(),
QualType Deduced = readType(*Loc.F, Record, Idx);
bool IsDecltypeAuto = Record[Idx++];
bool IsDependent = Deduced.isNull() ? Record[Idx++] : false;
- bool IsParameterPack = Record[Idx++];
- return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent,
- IsParameterPack);
+ return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent);
}
case TYPE_RECORD: {
= (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);
Capture *ToCapture = Lambda.Captures;
Lambda.MethodTyInfo = GetTypeSourceInfo(Record, Idx);
- Lambda.TheLambdaExpr = cast<LambdaExpr>(Reader.ReadExpr(F));
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
SourceLocation Loc = ReadSourceLocation(Record, Idx);
bool IsImplicit = Record[Idx++];
Record.push_back(T->isDecltypeAuto());
if (T->getDeducedType().isNull())
Record.push_back(T->isDependentType());
- Record.push_back(T->containsUnexpandedParameterPack());
Code = TYPE_AUTO;
}
Record.push_back(Lambda.ManglingNumber);
AddDeclRef(Lambda.ContextDecl, Record);
AddTypeSourceInfo(Lambda.MethodTyInfo, Record);
- AddStmt(Lambda.TheLambdaExpr);
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
LambdaExpr::Capture &Capture = Lambda.Captures[I];
AddSourceLocation(Capture.getLocation(), Record);
+++ /dev/null
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y
-
-//FIXME: These tests were written when return type deduction had not been implemented
-// for generic lambdas, hence
-template<class T> T id(T t);
-template<class ... Ts> int vfoo(Ts&& ... ts);
-auto GL1 = [](auto a, int i) -> int { return id(a); };
-
-auto GL2 = [](auto ... As) -> int { return vfoo(As...); };
-auto GL3 = [](int i, char c, auto* ... As) -> int { return vfoo(As...); };
-
-auto GL4 = [](int i, char c, auto* ... As) -> int { return vfoo(As...); };
-
-
-void foo() {
- auto GL1 = [](auto a, int i) -> int { return id(a); };
-
- auto GL2 = [](auto ... As) -> int { return vfoo(As...); };
-}
-
-
-int main()
-{
- auto l1 = [](auto a) -> int { return a + 5; };
- auto l2 = [](auto *p) -> int { return p + 5; };
-
- struct A { int i; char f(int) { return 'c'; } };
- auto l3 = [](auto &&ur,
- auto &lr,
- auto v,
- int i,
- auto* p,
- auto A::*memvar,
- auto (A::*memfun)(int),
- char c,
- decltype (v)* pv
- , auto (&array)[5]
- ) -> int { return v + i + c
- + array[0];
- };
- int arr[5] = {0, 1, 2, 3, 4 };
- int lval = 0;
- double d = 3.14;
- l3(3, lval, d, lval, &lval, &A::i, &A::f, 'c', &d, arr);
- auto l4 = [](decltype(auto) a) -> int { return 0; }; //expected-error{{decltype(auto)}}
- {
- struct Local {
- static int ifi(int i) { return i; }
- static char cfi(int) { return 'a'; }
- static double dfi(int i) { return i + 3.14; }
- static Local localfi(int) { return Local{}; }
- };
- auto l4 = [](auto (*fp)(int)) -> int { return fp(3); }; //expected-error{{no viable conversion from 'Local' to 'int'}}
- l4(&Local::ifi);
- l4(&Local::cfi);
- l4(&Local::dfi);
- l4(&Local::localfi); //expected-note{{in instantiation of function template specialization}}
- }
- {
- auto unnamed_parameter = [](auto, auto) -> void { };
- unnamed_parameter(3, '4');
- }
- {
- auto l = [](auto
- (*)(auto)) { }; //expected-error{{'auto' not allowed}}
- //FIXME: These diagnostics might need some work.
- auto l2 = [](char auto::*pm) { }; //expected-error{{cannot combine with previous}}\
- expected-error{{'pm' does not point into a class}}
- auto l3 = [](char (auto::*pmf)()) { }; //expected-error{{'auto' not allowed}}\
- expected-error{{'pmf' does not point into a class}}\
- expected-error{{function cannot return function type 'char ()'}}
- }
-}
-
-
+++ /dev/null
-// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -emit-llvm
-namespace return_type_deduction_ok {
-// FIXME: Once return type deduction is implemented for generic lambdas
-// this will need to be updated.
- auto l = [](auto a) ->auto { return a; }(2);
- auto l2 = [](auto a) ->decltype(auto) { return a; }(2);
- auto l3 = [](auto a) { return a; }(2);
-
-
-}
-
-namespace lambda_capturing {
-// FIXME: Once return type deduction is implemented for generic lambdas
-// this will need to be updated.
-void test() {
- int i = 10;
- auto L = [=](auto a) -> int { //expected-error{{unimplemented}}
- return i + a;
- };
- L(3);
-}
-
-}
-
-namespace nested_generic_lambdas {
-void test() {
- auto L = [](auto a) -> int {
- auto M = [](auto b, decltype(a) b2) -> int { //expected-error{{unimplemented}}
- return 1;
- };
- M(a, a);
- };
- L(3); //expected-note{{in instantiation of}}
-}
-}
-
-namespace conversion_operator {
-void test() {
- auto L = [](auto a) -> int { return a; };
- int (*fp)(int) = L; //expected-error{{no viable conversion}}
- }
-}
-
-namespace generic_lambda_as_default_argument_ok {
- void test(int i = [](auto a)->int { return a; }(3)) {
-
- }
-
-}
-
+++ /dev/null
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y\r
-\r
-// prvalue\r
-void prvalue() {\r
- auto&& x = [](auto a)->void { };\r
- auto& y = [](auto *a)->void { }; // expected-error{{cannot bind to a temporary of type}}\r
-}\r
-\r
-namespace std {\r
- class type_info;\r
-}\r
-\r
-struct P {\r
- virtual ~P();\r
-};\r
-\r
-void unevaluated_operand(P &p, int i) {\r
- // FIXME: this should only emit one error.\r
- int i2 = sizeof([](auto a, auto b)->void{}(3, '4')); // expected-error{{lambda expression in an unevaluated operand}} \\r
- // expected-error{{invalid application of 'sizeof'}}\r
- const std::type_info &ti1 = typeid([](auto &a) -> P& { static P p; return p; }(i));\r
- const std::type_info &ti2 = typeid([](auto) -> int { return i; }(i)); // expected-error{{lambda expression in an unevaluated operand}}\r
-}\r
int &e = [] (int &r) -> auto { return r; } (a); // expected-error {{cannot bind to a temporary}}
int &f = [] (int r) -> decltype(auto) { return r; } (a); // expected-error {{cannot bind to a temporary}}
int &g = [] (int r) -> decltype(auto) { return (r); } (a); // expected-warning {{reference to stack}}
-
-
-int test_explicit_auto_return()
-{
- struct X {};
- auto L = [](auto F, auto a) { return F(a); };
- auto M = [](auto a) -> auto { return a; }; // OK
- auto MRef = [](auto b) -> auto& { return b; }; //expected-warning{{reference to stack}}
- auto MPtr = [](auto c) -> auto* { return &c; }; //expected-warning{{address of stack}}
- auto MDeclType = [](auto&& d) -> decltype(auto) { return static_cast<decltype(d)>(d); }; //OK
- M(3);
-
- auto &&x = MDeclType(X{});
- auto &&x1 = M(X{});
- auto &&x2 = MRef(X{});//expected-note{{in instantiation of}}
- auto &&x3 = MPtr(X{}); //expected-note{{in instantiation of}}
- return 0;
-}
-
-int test_implicit_auto_return()
-{
- {
- auto M = [](auto a) { return a; };
- struct X {};
- X x = M(X{});
-
- }
-}
-
-int test_multiple_returns() {
- auto M = [](auto a) {
- bool k;
- if (k)
- return a;
- else
- return 5; //expected-error{{deduced as 'int' here}}
- };
- M(3); // OK
- M('a'); //expected-note{{in instantiation of}}
- return 0;
-}
-int test_no_parameter_list()
-{
- static int si = 0;
- auto M = [] { return 5; }; // OK
- auto M2 = [] -> auto&& { return si; }; // expected-error{{lambda requires '()'}}
- M();
-}
-
-int test_conditional_in_return() {
- auto Fac = [](auto f, auto n) {
- return n <= 0 ? n : f(f, n - 1) * n;
- };
- // FIXME: this test causes a recursive limit - need to error more gracefully.
- //Fac(Fac, 3);
-
-}
\ No newline at end of file
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
-// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -DCPP1Y
+// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify
void missing_lambda_declarator() {
[](){}();
switch (x) {
case 0: return get<void>();
case 1: return;
- case 2: return { 1, 2.0 }; //expected-error{{cannot deduce}}
+ case 2: return { 1, 2.0 }; // expected-error{{cannot deduce lambda return type from initializer list}}
}
}(7);
}
+++ /dev/null
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y -emit-llvm\r
-\r
-namespace test_factorial {\r
-\r
-auto Fact = [](auto Self, unsigned n) -> unsigned {\r
- return !n ? 1 : Self(Self, n - 1) * n;\r
-};\r
-\r
-auto six = Fact(Fact, 3);\r
-\r
-}\r
-\r
-namespace overload_generic_lambda {\r
- template <class F1, class F2> struct overload : F1, F2 {\r
- using F1::operator();\r
- using F2::operator();\r
- overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }\r
- };\r
-\r
- auto NumParams = [](auto Self, auto h, auto ... rest) -> unsigned {\r
- return 1 + Self(Self, rest...);\r
- };\r
- auto Base = [](auto Self, auto h) -> unsigned {\r
- return 1;\r
- };\r
- overload<decltype(Base), decltype(NumParams)> O(Base, NumParams);\r
- int num_params = O(O, 5, 3, "abc", 3.14, 'a');\r
-}\r
-\r
-\r
-namespace overload_generic_lambda_return_type_deduction {\r
- template <class F1, class F2> struct overload : F1, F2 {\r
- using F1::operator();\r
- using F2::operator();\r
- overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }\r
- };\r
-\r
- auto NumParams = [](auto Self, auto h, auto ... rest) {\r
- return 1 + Self(Self, rest...);\r
- };\r
- auto Base = [](auto Self, auto h) {\r
- return 1;\r
- };\r
- overload<decltype(Base), decltype(NumParams)> O(Base, NumParams);\r
- int num_params = O(O, 5, 3, "abc", 3.14, 'a');\r
-}\r
-\r
-namespace test_standard_p5 {\r
-// FIXME: This test should eventually compile without an explicit trailing return type\r
-auto glambda = [](auto a, auto&& b) ->bool { return a < b; };\r
-bool b = glambda(3, 3.14); // OK\r
-\r
-}\r
-namespace test_deduction_failure {\r
- int test() {\r
- auto g = [](auto *a) { //expected-note{{candidate template ignored}}\r
- return a;\r
- };\r
- struct X { };\r
- X *x;\r
- g(x);\r
- g(3); //expected-error{{no matching function}}\r
- return 0;\r
- }\r
-\r
-}\r
- \r
-namespace test_instantiation_or_sfinae_failure {\r
-int test2() {\r
- {\r
- auto L = [](auto *a) { \r
- return (*a)(a); }; //expected-error{{called object type 'double' is not a function}}\r
- //l(&l);\r
- double d;\r
- L(&d); //expected-note{{in instantiation of}}\r
- auto M = [](auto b) { return b; };\r
- L(&M); // ok\r
- }\r
- {\r
- auto L = [](auto *a) ->decltype (a->foo()) { //expected-note2{{candidate template ignored:}}\r
- return (*a)(a); }; \r
- //l(&l);\r
- double d;\r
- L(&d); //expected-error{{no matching function for call}} \r
- auto M = [](auto b) { return b; };\r
- L(&M); //expected-error{{no matching function for call}} \r
- \r
- }\r
- return 0;\r
-}\r
-\r
-\r
-}\r
- \r
-namespace test_misc {\r
-auto GL = [](auto a, decltype(a) b) //expected-note{{candidate function}} \r
- -> int { return a + b; };\r
-\r
-void test() {\r
- struct X { };\r
- GL(3, X{}); //expected-error{{no matching function}}\r
-}\r
-\r
-void test2() {\r
- auto l = [](auto *a) -> int { \r
- (*a)(a); return 0; }; //expected-error{{called object type 'double' is not a function}}\r
- l(&l);\r
- double d;\r
- l(&d); //expected-note{{in instantiation of}}\r
-}\r
-\r
-}\r
-\r
-namespace nested_lambdas {\r
- int test() {\r
- auto L = [](auto a) {\r
- return [=](auto b) { //expected-error{{unimplemented}}\r
- return a + b;\r
- };\r
- };\r
- // auto M = L(3.14);\r
- // return M('4'); \r
- }\r
- auto get_lambda() {\r
- return [](auto a) {\r
- return a; \r
- };\r
- };\r
- \r
- int test2() {\r
- auto L = get_lambda();\r
- L(3);\r
- }\r
-}\r
-\r