summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp17
-rw-r--r--clang/lib/AST/ASTImporter.cpp4
-rw-r--r--clang/lib/AST/DeclCXX.cpp45
-rw-r--r--clang/lib/AST/ExprCXX.cpp14
-rw-r--r--clang/lib/AST/Type.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--clang/lib/Parse/ParseDecl.cpp35
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp17
-rw-r--r--clang/lib/Parse/Parser.cpp1
-rw-r--r--clang/lib/Sema/Sema.cpp25
-rw-r--r--clang/lib/Sema/SemaDecl.cpp45
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp15
-rw-r--r--clang/lib/Sema/SemaLambda.cpp159
-rw-r--r--clang/lib/Sema/SemaOverload.cpp4
-rw-r--r--clang/lib/Sema/SemaStmt.cpp66
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp15
-rw-r--r--clang/lib/Sema/SemaType.cpp43
-rw-r--r--clang/lib/Sema/TreeTransform.h26
-rw-r--r--clang/lib/Serialization/ASTReader.cpp4
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp1
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp2
21 files changed, 424 insertions, 120 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 29ddb37525d..b1b52fb1c57 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3649,20 +3649,24 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType,
/// 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) const {
- if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent)
+ bool IsDependent, bool IsParameterPack) const {
+ if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent &&
+ !IsParameterPack)
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);
+ AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent,
+ IsParameterPack);
if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(AT, 0);
AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType,
IsDecltypeAuto,
- IsDependent);
+ IsDependent,
+ IsParameterPack);
Types.push_back(AT);
if (InsertPos)
AutoTypes.InsertNode(AT, InsertPos);
@@ -3702,7 +3706,8 @@ QualType ASTContext::getAutoDeductType() const {
if (AutoDeductTy.isNull())
AutoDeductTy = QualType(
new (*this, TypeAlignment) AutoType(QualType(), /*decltype(auto)*/false,
- /*dependent*/false),
+ /*dependent*/false,
+ /*IsParameterPack*/false),
0);
return AutoDeductTy;
}
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 922172701f0..f03b66dfd88 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1709,7 +1709,9 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) {
return QualType();
}
- return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto());
+ return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto(),
+ /*IsDependent*/false,
+ T->containsUnexpandedParameterPack());
}
QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index ccd8220a684..b50aa9337fe 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -20,6 +20,7 @@
#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;
@@ -930,6 +931,40 @@ bool CXXRecordDecl::isCLike() const {
return isPOD() && data().HasOnlyCMembers;
}
+bool CXXRecordDecl::isGenericLambda() const {
+ return isLambda() &&
+ getLambdaCallOperator()->getDescribedFunctionTemplate();
+}
+
+CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
+ if (!isLambda()) return 0;
+ DeclarationName Name =
+ getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
+ DeclContext::lookup_const_result Calls = lookup(Name);
+
+ assert(!Calls.empty() && "Missing lambda call operator!");
+ assert(Calls.size() == 1 && "More than one lambda call operator!");
+
+ NamedDecl *CallOp = Calls.front();
+ if (FunctionTemplateDecl *CallOpTmpl =
+ dyn_cast<FunctionTemplateDecl>(CallOp))
+ return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl());
+
+ return cast<CXXMethodDecl>(CallOp);
+}
+
+CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
+ if (!isLambda()) return 0;
+ DeclarationName Name =
+ &getASTContext().Idents.get(getLambdaStaticInvokerName());
+ DeclContext::lookup_const_result Invoker = lookup(Name);
+ if (Invoker.empty()) return 0;
+ assert(Invoker.size() == 1 && "More than one static invoker operator!");
+ CXXMethodDecl *Result = cast<CXXMethodDecl>(Invoker.front());
+ return Result;
+
+}
+
void CXXRecordDecl::getCaptureFields(
llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
FieldDecl *&ThisCapture) const {
@@ -947,6 +982,14 @@ void CXXRecordDecl::getCaptureFields(
}
}
+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;
@@ -1493,7 +1536,7 @@ bool CXXMethodDecl::hasInlineBody() const {
bool CXXMethodDecl::isLambdaStaticInvoker() const {
return getParent()->isLambda() &&
- getIdentifier() && getIdentifier()->getName() == "__invoke";
+ getParent()->getLambdaStaticInvoker() == this;
}
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 0609eb1d65d..28794d4f621 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1026,13 +1026,13 @@ CXXRecordDecl *LambdaExpr::getLambdaClass() const {
CXXMethodDecl *LambdaExpr::getCallOperator() const {
CXXRecordDecl *Record = getLambdaClass();
- 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;
+ return Record->getLambdaCallOperator();
+}
+
+TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
+ CXXRecordDecl *Record = getLambdaClass();
+ return Record->getGenericLambdaTemplateParameterList();
+
}
CompoundStmt *LambdaExpr::getBody() const {
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 44da348b0b7..bb6d0bf05d1 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -589,6 +589,10 @@ namespace {
AutoType *VisitAttributedType(const AttributedType *T) {
return Visit(T->getModifiedType());
}
+ AutoType *VisitPackExpansionType(const PackExpansionType *T) {
+ return Visit(T->getPattern());
+ }
+
};
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index da8db172f50..c271d7c6268 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -700,7 +700,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
EmitLambdaToBlockPointerBody(Args);
} else if (isa<CXXMethodDecl>(FD) &&
cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {
- // The lambda "__invoke" function is special, because it forwards or
+ // The lambda static invoker 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) &&
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 392535acef2..4c4ce874822 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4670,6 +4670,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// 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() &&
@@ -4988,7 +4989,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
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. */
@@ -5009,7 +5009,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
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);
@@ -5240,7 +5241,6 @@ void Parser::ParseParameterDeclarationClause(
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
@@ -5270,16 +5270,21 @@ void Parser::ParseParameterDeclarationClause(
ParseDeclarationSpecifiers(DS);
- // Parse the declarator. This is "PrototypeContext", because we must
- // accept either 'declarator' or 'abstract-declarator' here.
- Declarator ParmDecl(DS, Declarator::PrototypeContext);
- ParseDeclarator(ParmDecl);
+
+ // 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 GNU attributes, if present.
- MaybeParseGNUAttributes(ParmDecl);
+ MaybeParseGNUAttributes(ParmDeclarator);
// Remember this parsed parameter in ParamInfo.
- IdentifierInfo *ParmII = ParmDecl.getIdentifier();
+ IdentifierInfo *ParmII = ParmDeclarator.getIdentifier();
// DefArgToks is used when the parsing of default arguments needs
// to be delayed.
@@ -5287,8 +5292,8 @@ void Parser::ParseParameterDeclarationClause(
// If no parameter was specified, verify that *something* was specified,
// otherwise we have a missing type and identifier.
- if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 &&
- ParmDecl.getNumTypeObjects() == 0) {
+ if (DS.isEmpty() && ParmDeclarator.getIdentifier() == 0 &&
+ ParmDeclarator.getNumTypeObjects() == 0) {
// Completely missing, emit error.
Diag(DSStart, diag::err_missing_param);
} else {
@@ -5297,8 +5302,8 @@ void Parser::ParseParameterDeclarationClause(
// Inform the actions module about the parameter declarator, so it gets
// added to the current scope.
- Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
-
+ Decl *Param = Actions.ActOnParamDeclarator(getCurScope(),
+ ParmDeclarator);
// 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
@@ -5359,8 +5364,8 @@ void Parser::ParseParameterDeclarationClause(
}
ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
- ParmDecl.getIdentifierLoc(), Param,
- DefArgToks));
+ ParmDeclarator.getIdentifierLoc(),
+ Param, DefArgToks));
}
// If the next token is a comma, consume it and keep reading arguments.
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 9ac6d435067..1ab70475e53 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -20,6 +20,7 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "llvm/Support/ErrorHandling.h"
+#include "clang/AST/DeclTemplate.h"
using namespace clang;
@@ -908,12 +909,16 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
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,
@@ -931,9 +936,17 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
SourceLocation EllipsisLoc;
- if (Tok.isNot(tok::r_paren))
+
+ if (Tok.isNot(tok::r_paren)) {
+ sema::LambdaScopeInfo *LSI = Actions.getCurLambda();
+ if (getLangOpts().CPlusPlus1y)
+ Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
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;
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 866572ceab9..6ee97d49368 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1175,7 +1175,6 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
// 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()) {
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 6cc596cec1b..aab03897963 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1007,10 +1007,17 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
BlockScope, Block));
}
-void Sema::PushLambdaScope(CXXRecordDecl *Lambda,
- CXXMethodDecl *CallOperator) {
- FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda,
- CallOperator));
+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::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
@@ -1066,6 +1073,16 @@ LambdaScopeInfo *Sema::getCurLambda() {
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 &&
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 80863e35e29..d5d890456e5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -35,6 +35,7 @@
#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"
@@ -8909,6 +8910,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
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) {
@@ -9015,6 +9017,14 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
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;
}
@@ -9268,9 +9278,38 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
FD = FunTmpl->getTemplatedDecl();
else
FD = cast<FunctionDecl>(D);
-
- // Enter a new function scope
- PushFunctionScope();
+ // 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();
// See if this is a redefinition.
if (!FD->isLateTemplateParsed())
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 6ebfb57974e..bde9c15c998 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -32,6 +32,7 @@
#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"
@@ -10015,29 +10016,27 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv)
{
- CXXRecordDecl *Lambda = Conv->getParent();
+ CXXRecordDecl *LambdaClass = Conv->getParent();
// Make sure that the lambda call operator is marked used.
- markLambdaCallOperatorUsed(*this, Lambda);
+ markLambdaCallOperatorUsed(*this, LambdaClass);
Conv->setUsed();
SynthesizedFunctionScope Scope(*this, Conv);
DiagnosticErrorTrap Trap(Diags);
- // Return the address of the __invoke function.
- DeclarationName InvokeName = &Context.Idents.get("__invoke");
- CXXMethodDecl *Invoke
- = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front());
+ CXXMethodDecl *Invoke = LambdaClass->getLambdaStaticInvoker();
+
Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(),
VK_LValue, Conv->getLocation()).take();
- assert(FunctionRef && "Can't refer to __invoke function?");
+ assert(FunctionRef && "Can't refer to lambda static invoker 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();
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index ae3a938333f..bed71a676f8 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -14,6 +14,7 @@
#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"
@@ -120,11 +121,69 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
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
@@ -152,6 +211,17 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
// 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()) {
@@ -177,15 +247,16 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
return Method;
}
-LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
+void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
+ CXXMethodDecl *CallOperator,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc,
bool ExplicitParams,
bool ExplicitResultType,
bool Mutable) {
- PushLambdaScope(CallOperator->getParent(), CallOperator);
- LambdaScopeInfo *LSI = getCurLambda();
+ LSI->CallOperator = CallOperator;
+ LSI->Lambda = CallOperator->getParent();
if (CaptureDefault == LCD_ByCopy)
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
else if (CaptureDefault == LCD_ByRef)
@@ -208,8 +279,6 @@ LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
} else {
LSI->HasImplicitReturnType = true;
}
-
- return LSI;
}
void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
@@ -358,7 +427,7 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns,
}
void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
- assert(CSI.HasImplicitReturnType);
+ assert(CSI.HasImplicitReturnType || CSI.ReturnType->isUndeducedType());
// C++ Core Issue #975, proposed resolution:
// If a lambda-expression does not include a trailing-return-type,
@@ -392,7 +461,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
// 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())
+ if (CSI.ReturnType->isDependentType() || CSI.ReturnType->isUndeducedType())
return;
// Try to apply the enum-fuzz rule.
@@ -519,15 +588,25 @@ FieldDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef,
}
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;
- if (Scope *TmplScope = CurScope->getTemplateParamParent())
- if (!TmplScope->decl_empty())
+ 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())
KnownDependent = true;
-
+ }
// Determine the signature of the call operator.
TypeSourceInfo *MethodTyInfo;
bool ExplicitParams = true;
@@ -542,7 +621,11 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
FunctionProtoType::ExtProtoInfo EPI;
EPI.HasTrailingReturn = true;
EPI.TypeQuals |= DeclSpec::TQ_const;
- QualType MethodTy = Context.getFunctionType(Context.DependentTy, None,
+ // 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,
EPI);
MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
ExplicitParams = false;
@@ -560,14 +643,15 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
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.
@@ -588,7 +672,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
MethodTyInfo, EndLoc, Params);
-
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
@@ -598,9 +681,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// Introduce the function call operator as the current declaration context.
PushDeclContext(CurScope, Method);
- // Introduce the lambda scope.
- LambdaScopeInfo *LSI
- = enterLambdaScope(Method,
+ // Build the lambda scope.
+ buildLambdaScope(LSI, Method,
Intro.Range,
Intro.Default, Intro.DefaultLoc,
ExplicitParams,
@@ -812,6 +894,8 @@ static void addFunctionPointerConversion(Sema &S,
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>();
@@ -849,10 +933,9 @@ static void addFunctionPointerConversion(Sema &S,
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
Class->addDecl(Conversion);
-
- // Add a non-static member function "__invoke" that will be the result of
- // the conversion.
- Name = &S.Context.Idents.get("__invoke");
+ // 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());
CXXMethodDecl *Invoke
= CXXMethodDecl::Create(S.Context, Class, Loc,
DeclarationNameInfo(Name, Loc), FunctionTy,
@@ -1000,8 +1083,11 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
// 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) {
+ if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus1y) {
deduceClosureReturnType(*LSI);
// - if there are no return statements in the
@@ -1019,13 +1105,18 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
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);
- Class->addDecl(CallOperator);
+ Decl *TemplateOrNonTemplateCallOperatorDecl =
+ !CallOperator->getDescribedFunctionTemplate() ? cast<Decl>(CallOperator)
+ : CallOperator->getDescribedFunctionTemplate();
+
+ TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);
+ Class->addDecl(TemplateOrNonTemplateCallOperatorDecl);
+
PopExpressionEvaluationContext();
// C++11 [expr.prim.lambda]p6:
@@ -1065,7 +1156,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
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).
@@ -1085,7 +1176,15 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
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);
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 06d1f0b0e2d..33dbf14580b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -8670,6 +8670,10 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated,
}
}
}
+ // 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;
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 0570a60a0a0..5434e987e9e 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2487,12 +2487,31 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// [expr.prim.lambda]p4 in C++11; block literals follow the same rules.
CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction());
QualType FnRetType = CurCap->ReturnType;
-
- // 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.
+ 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)) {
if (RetValExp && !isa<InitListExpr>(RetValExp)) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp);
if (Result.isInvalid())
@@ -2500,13 +2519,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
RetValExp = Result.take();
if (!CurContext->isDependentContext()) {
- 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();
+ FnRetType = RetValExp->getType();
} else
FnRetType = CurCap->ReturnType = Context.DependentTy;
} else {
@@ -2517,7 +2530,6 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
Diag(ReturnLoc, diag::err_lambda_return_init_list)
<< RetValExp->getSourceRange();
}
-
FnRetType = Context.VoidTy;
}
@@ -2526,7 +2538,8 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (CurCap->ReturnType.isNull())
CurCap->ReturnType = FnRetType;
} else if (AutoType *AT =
- FnRetType.isNull() ? 0 : FnRetType->getContainedAutoType()) {
+ (FnRetType.isNull() || !LambdaSI) ? 0
+ : FnRetType->getContainedAutoType()) {
// In C++1y, the return type may involve 'auto'.
FunctionDecl *FD = cast<LambdaScopeInfo>(CurCap)->CallOperator;
if (CurContext->isDependentContext()) {
@@ -2534,7 +2547,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// 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 = Context.DependentTy;
+ CurCap->ReturnType = FnRetType;
} else if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
FD->setInvalidDecl();
return StmtError();
@@ -2564,7 +2577,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// 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()) {
+ if (FnRetType->isDependentType() || FnRetType->isUndeducedType()) {
// Delay processing for now. TODO: there are lots of dependent
// types we can conclusively prove aren't void.
} else if (FnRetType->isVoidType()) {
@@ -2624,7 +2637,6 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
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,
@@ -2634,7 +2646,6 @@ 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.
@@ -2692,9 +2703,18 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
AutoType *NewAT = Deduced->getContainedAutoType();
if (!FD->isDependentContext() &&
!Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) {
- Diag(ReturnLoc, diag::err_auto_fn_different_deductions)
- << (AT->isDecltypeAuto() ? 1 : 0)
- << NewAT->getDeducedType() << AT->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();
+ }
return true;
}
} else if (!FD->isInvalidDecl()) {
@@ -2710,10 +2730,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// 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()) {
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index c8669ae7b82..813f71d40d1 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3766,7 +3766,8 @@ namespace {
QualType Result =
SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement,
TL.getTypePtr()->isDecltypeAuto(),
- Dependent);
+ Dependent, TL.getTypePtr()->
+ containsUnexpandedParameterPack());
AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
@@ -3907,8 +3908,16 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
return DAR_Succeeded;
}
-QualType Sema::SubstAutoType(QualType Type, QualType Deduced) {
- return SubstituteAutoTransform(*this, Deduced).TransformType(Type);
+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);
}
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 6998827e162..2dabfb2bbc2 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -781,7 +781,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// specified with a trailing return type or inferred.
if (declarator.getContext() == Declarator::LambdaExprContext ||
isOmittedBlockReturnType(declarator)) {
- Result = Context.DependentTy;
+ // 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;
break;
}
@@ -1006,11 +1012,17 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
case DeclSpec::TST_auto:
// TypeQuals handled by caller.
- Result = Context.getAutoType(QualType(), /*decltype(auto)*/false);
+ Result = Context.getAutoType(QualType(),
+ /*decltype(auto)*/false,
+ /*IsDependent*/ false,
+ /*IsParameterPack*/ declarator.hasEllipsis());
break;
case DeclSpec::TST_decltype_auto:
- Result = Context.getAutoType(QualType(), /*decltype(auto)*/true);
+ Result = Context.getAutoType(QualType(),
+ /*decltype(auto)*/true,
+ /*IsDependent*/ false,
+ /*IsParameterPack*/ false);
break;
case DeclSpec::TST_unknown_anytype:
@@ -1557,7 +1569,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
ASM = ArrayType::Normal;
}
} else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
- !T->isIncompleteType()) {
+ !T->isIncompleteType() && !T->isUndeducedType()) {
// Is the array too large?
unsigned ActiveSizeBits
= ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
@@ -2097,6 +2109,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// 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;
@@ -2109,7 +2122,12 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::ObjCParameterContext:
case Declarator::ObjCResultContext:
case Declarator::PrototypeContext:
- Error = 0; // Function prototype
+ Error = 0;
+ break;
+ case Declarator::LambdaExprParameterContext:
+ if (!(SemaRef.getLangOpts().CPlusPlus1y
+ && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))
+ Error = 0;
break;
case Declarator::MemberContext:
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
@@ -2189,8 +2207,13 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
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
@@ -2240,6 +2263,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType(true);
break;
case Declarator::PrototypeContext:
+ case Declarator::LambdaExprParameterContext:
case Declarator::ObjCParameterContext:
case Declarator::ObjCResultContext:
case Declarator::KNRTypeListContext:
@@ -2613,8 +2637,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
}
-
- if (const AutoType *AT = T->getContainedAutoType()) {
+ 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)) {
// We've already diagnosed this for decltype(auto).
if (!AT->isDecltypeAuto())
S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
@@ -3110,6 +3137,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// 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
@@ -3128,7 +3156,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
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
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 9e5738394ea..6e69bdc5128 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -782,7 +782,10 @@ public:
// 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.
- return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto);
+ // FIXME: Can we assume the same about IsParameterPack?
+ return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto,
+ /*IsDependent*/ false,
+ /*IsParameterPack*/ false);
}
/// \brief Build a new template specialization type.
@@ -3494,7 +3497,9 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
Qs.removeObjCLifetime();
Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(),
Qs);
- Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto());
+ Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(),
+ AutoTy->isDependentType(),
+ AutoTy->containsUnexpandedParameterPack());
TLB.TypeWasModifiedSafely(Result);
} else {
// Otherwise, complain about the addition of a qualifier to an
@@ -8193,6 +8198,14 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
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
@@ -8215,7 +8228,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
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(),
@@ -8250,9 +8266,9 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
// Introduce the context of the call operator.
Sema::ContextRAII SavedContext(getSema(), CallOperator);
+ LambdaScopeInfo *const LSI = getSema().getCurLambda();
// Enter the scope of the lambda.
- sema::LambdaScopeInfo *LSI
- = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(),
+ getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(),
E->getCaptureDefault(),
E->getCaptureDefaultLoc(),
E->hasExplicitParameters(),
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 462c2d3db97..5b1a608e600 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -4740,7 +4740,9 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
QualType Deduced = readType(*Loc.F, Record, Idx);
bool IsDecltypeAuto = Record[Idx++];
bool IsDependent = Deduced.isNull() ? Record[Idx++] : false;
- return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent);
+ bool IsParameterPack = Record[Idx++];
+ return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent,
+ IsParameterPack);
}
case TYPE_RECORD: {
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 7099d32b3d5..74e99379a4b 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1201,6 +1201,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
= (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++];
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index d8485300bec..01bc9cbc377 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -253,6 +253,7 @@ void ASTTypeWriter::VisitAutoType(const AutoType *T) {
Record.push_back(T->isDecltypeAuto());
if (T->getDeducedType().isNull())
Record.push_back(T->isDependentType());
+ Record.push_back(T->containsUnexpandedParameterPack());
Code = TYPE_AUTO;
}
@@ -5136,6 +5137,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec
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);
OpenPOWER on IntegriCloud