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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188410 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c583674..9d4280a 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2459,7 +2459,7 @@
// 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 @@
// 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 @@
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.