diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 |
4 files changed, 47 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c5836746221..9d4280ae9b9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2459,7 +2459,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, // cannot be overloaded. // Go back to the type source info to compare the declared return types, - // per C++1y [dcl.type.auto]p??: + // per C++1y [dcl.type.auto]p13: // Redeclarations or specializations of a function or function template // with a declared return type that uses a placeholder type shall also // use that placeholder, not a deduced type. @@ -2494,9 +2494,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, // defined, copy the deduced value from the old declaration. AutoType *OldAT = Old->getResultType()->getContainedAutoType(); if (OldAT && OldAT->isDeduced()) { - New->setType(SubstAutoType(New->getType(), OldAT->getDeducedType())); + New->setType( + SubstAutoType(New->getType(), + OldAT->isDependentType() ? Context.DependentTy + : OldAT->getDeducedType())); NewQType = Context.getCanonicalType( - SubstAutoType(NewQType, OldAT->getDeducedType())); + SubstAutoType(NewQType, + OldAT->isDependentType() ? Context.DependentTy + : OldAT->getDeducedType())); } } @@ -6688,6 +6693,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual); } + if (getLangOpts().CPlusPlus1y && NewFD->isDependentContext() && + NewFD->getResultType()->isUndeducedType()) { + // If the function template is referenced directly (for instance, as a + // member of the current instantiation), pretend it has a dependent type. + // This is not really justified by the standard, but is the only sane + // thing to do. + const FunctionProtoType *FPT = + NewFD->getType()->castAs<FunctionProtoType>(); + QualType Result = SubstAutoType(FPT->getResultType(), + Context.DependentTy); + NewFD->setType(Context.getFunctionType(Result, FPT->getArgTypes(), + FPT->getExtProtoInfo())); + } + // C++ [dcl.fct.spec]p3: // The inline specifier shall not appear on a block scope function // declaration. diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 46e350bfa28..87e7e03b847 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -2611,7 +2611,21 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc(); QualType Deduced; - if (RetExpr) { + 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. + Diag(RetExpr->getExprLoc(), diag::err_auto_fn_return_init_list); + return true; + } + + if (FD->isDependentContext()) { + // C++1y [dcl.spec.auto]p12: + // Return type deduction [...] occurs when the definition is + // instantiated even if the function body contains a return + // statement with a non-type-dependent operand. + assert(AT->isDeduced() && "should have deduced to dependent type"); + return false; + } else if (RetExpr) { // If the deduction is for a return statement and the initializer is // a braced-init-list, the program is ill-formed. if (isa<InitListExpr>(RetExpr)) { @@ -2652,7 +2666,8 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, // the program is ill-formed. if (AT->isDeduced() && !FD->isInvalidDecl()) { AutoType *NewAT = Deduced->getContainedAutoType(); - if (!Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) { + 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(); @@ -2696,13 +2711,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // FIXME: Add a flag to the ScopeInfo to indicate whether we're performing // deduction. - bool HasDependentReturnType = FnRetType->isDependentType(); if (getLangOpts().CPlusPlus1y) { if (AutoType *AT = FnRetType->getContainedAutoType()) { FunctionDecl *FD = cast<FunctionDecl>(CurContext); - if (CurContext->isDependentContext()) - HasDependentReturnType = true; - else if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { + if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { FD->setInvalidDecl(); return StmtError(); } else { @@ -2711,6 +2723,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } } + bool HasDependentReturnType = FnRetType->isDependentType(); + ReturnStmt *Result = 0; if (FnRetType->isVoidType()) { if (RetValExp) { diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 898ced2dc1a..c8669ae7b82 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2581,7 +2581,6 @@ Sema::SubstituteExplicitTemplateArguments( } // Instantiate the return type. - // FIXME: exception-specifications? QualType ResultType; { // C++11 [expr.prim.general]p3: @@ -3555,11 +3554,11 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // If the function has a deduced return type, substitute it for a dependent // type so that we treat it as a non-deduced context in what follows. - bool HasUndeducedReturnType = false; + bool HasDeducedReturnType = false; if (getLangOpts().CPlusPlus1y && InOverloadResolution && - Function->getResultType()->isUndeducedType()) { + Function->getResultType()->getContainedAutoType()) { FunctionType = SubstAutoType(FunctionType, Context.DependentTy); - HasUndeducedReturnType = true; + HasDeducedReturnType = true; } if (!ArgFunctionType.isNull()) { @@ -3581,7 +3580,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // If the function has a deduced return type, deduce it now, so we can check // that the deduced function type matches the requested type. - if (HasUndeducedReturnType && + if (HasDeducedReturnType && Specialization->getResultType()->isUndeducedType() && DeduceReturnType(Specialization, Info.getLocation(), false)) return TDK_MiscellaneousDeductionFailure; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3379ebcd900..3cb20c79af5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3161,7 +3161,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (Function->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDeclaration && !PatternDecl->isInlined() && - !PatternDecl->getResultType()->isUndeducedType()) + !PatternDecl->getResultType()->getContainedAutoType()) return; if (PatternDecl->isInlined()) |