r188410 - PR16875: The return type of a dependent function type is visible when it's
Richard Smith
richard-llvm at metafoo.co.uk
Wed Aug 14 13:16:31 PDT 2013
Author: rsmith
Date: Wed Aug 14 15:16:31 2013
New Revision: 188410
URL: http://llvm.org/viewvc/llvm-project?rev=188410&view=rev
Log:
PR16875: The return type of a dependent function type is visible when it's
referenced as a member of the current instantiation. In that case, deduce the
type of the function to a dependent type rather than exposing an undeduced auto
type to the rest of the current instantiation.
The standard doesn't really say that the type is dependent in this case; I'll
bring this up with CWG.
Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=188410&r1=188409&r2=188410&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Aug 14 15:16:31 2013
@@ -2459,7 +2459,7 @@ bool Sema::MergeFunctionDecl(FunctionDec
// 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(FunctionDec
// 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,
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.
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=188410&r1=188409&r2=188410&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Aug 14 15:16:31 2013
@@ -2611,7 +2611,21 @@ bool Sema::DeduceFunctionTypeFromReturnE
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::DeduceFunctionTypeFromReturnE
// 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 Ret
// 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 Ret
}
}
+ bool HasDependentReturnType = FnRetType->isDependentType();
+
ReturnStmt *Result = 0;
if (FnRetType->isVoidType()) {
if (RetValExp) {
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=188410&r1=188409&r2=188410&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Aug 14 15:16:31 2013
@@ -2581,7 +2581,6 @@ Sema::SubstituteExplicitTemplateArgument
}
// Instantiate the return type.
- // FIXME: exception-specifications?
QualType ResultType;
{
// C++11 [expr.prim.general]p3:
@@ -3555,11 +3554,11 @@ Sema::DeduceTemplateArguments(FunctionTe
// 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(FunctionTe
// 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;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=188410&r1=188409&r2=188410&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Aug 14 15:16:31 2013
@@ -3161,7 +3161,7 @@ void Sema::InstantiateFunctionDefinition
if (Function->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration &&
!PatternDecl->isInlined() &&
- !PatternDecl->getResultType()->isUndeducedType())
+ !PatternDecl->getResultType()->getContainedAutoType())
return;
if (PatternDecl->isInlined())
Modified: cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp?rev=188410&r1=188409&r2=188410&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp Wed Aug 14 15:16:31 2013
@@ -376,3 +376,26 @@ namespace MemberTemplatesWithDeduction {
}
}
+
+namespace CurrentInstantiation {
+ // PR16875
+ template<typename T> struct S {
+ auto f() { return T(); }
+ int g() { return f(); }
+ auto h(bool b) {
+ if (b)
+ return T();
+ return h(true);
+ }
+ };
+ int k1 = S<int>().g();
+ int k2 = S<int>().h(false);
+
+ template<typename T> struct U {
+ auto f(); // expected-note {{here}}
+ int g() { return f(); } // expected-error {{cannot be used before it is defined}}
+ };
+ template int U<int>::g(); // expected-note {{in instantiation of}}
+ template<typename T> auto U<T>::f() { return T(); }
+ template int U<short>::g(); // ok
+}
More information about the cfe-commits
mailing list