r290660 - Mark 'auto' as dependent when instantiating the type of a non-type template
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 27 22:27:19 PST 2016
Author: rsmith
Date: Wed Dec 28 00:27:18 2016
New Revision: 290660
URL: http://llvm.org/viewvc/llvm-project?rev=290660&view=rev
Log:
Mark 'auto' as dependent when instantiating the type of a non-type template
parameter. Fixes failed deduction for 'auto' non-type template parameters
nested within templates.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=290660&r1=290659&r2=290660&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Dec 28 00:27:18 2016
@@ -5790,7 +5790,10 @@ public:
SourceLocation EqualLoc,
ParsedType DefaultArg);
+ QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
+ SourceLocation Loc);
QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
+
Decl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
unsigned Position,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=290660&r1=290659&r2=290660&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Dec 28 00:27:18 2016
@@ -729,8 +729,22 @@ Decl *Sema::ActOnTypeParameter(Scope *S,
///
/// \returns the (possibly-promoted) parameter type if valid;
/// otherwise, produces a diagnostic and returns a NULL type.
-QualType
-Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
+QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
+ SourceLocation Loc) {
+ if (TSI->getType()->isUndeducedType()) {
+ // C++1z [temp.dep.expr]p3:
+ // An id-expression is type-dependent if it contains
+ // - an identifier associated by name lookup with a non-type
+ // template-parameter declared with a type that contains a
+ // placeholder type (7.1.7.4),
+ TSI = SubstAutoTypeSourceInfo(TSI, Context.DependentTy);
+ }
+
+ return CheckNonTypeTemplateParameterType(TSI->getType(), Loc);
+}
+
+QualType Sema::CheckNonTypeTemplateParameterType(QualType T,
+ SourceLocation Loc) {
// We don't allow variably-modified types as the type of non-type template
// parameters.
if (T->isVariablyModifiedType()) {
@@ -759,10 +773,6 @@ Sema::CheckNonTypeTemplateParameterType(
T->isDependentType() ||
// Allow use of auto in template parameter declarations.
T->isUndeducedType()) {
- if (T->isUndeducedType()) {
- Diag(Loc, diag::warn_cxx14_compat_template_nontype_parm_auto_type)
- << QualType(T->getContainedAutoType(), 0);
- }
// C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter
// are ignored when determining its type.
return T.getUnqualifiedType();
@@ -788,13 +798,18 @@ Decl *Sema::ActOnNonTypeTemplateParamete
SourceLocation EqualLoc,
Expr *Default) {
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
- QualType T = TInfo->getType();
+
+ if (TInfo->getType()->isUndeducedType()) {
+ Diag(D.getIdentifierLoc(),
+ diag::warn_cxx14_compat_template_nontype_parm_auto_type)
+ << QualType(TInfo->getType()->getContainedAutoType(), 0);
+ }
assert(S->isTemplateParamScope() &&
"Non-type template parameter not in template parameter scope!");
bool Invalid = false;
- T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc());
+ QualType T = CheckNonTypeTemplateParameterType(TInfo, D.getIdentifierLoc());
if (T.isNull()) {
T = Context.IntTy; // Recover with an 'int' type.
Invalid = true;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=290660&r1=290659&r2=290660&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Dec 28 00:27:18 2016
@@ -2085,18 +2085,18 @@ Decl *TemplateDeclInstantiator::VisitNon
ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes());
ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes());
for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
- TypeSourceInfo *NewDI =SemaRef.SubstType(D->getExpansionTypeSourceInfo(I),
- TemplateArgs,
- D->getLocation(),
- D->getDeclName());
+ TypeSourceInfo *NewDI =
+ SemaRef.SubstType(D->getExpansionTypeSourceInfo(I), TemplateArgs,
+ D->getLocation(), D->getDeclName());
if (!NewDI)
return nullptr;
- ExpandedParameterPackTypesAsWritten.push_back(NewDI);
- QualType NewT =SemaRef.CheckNonTypeTemplateParameterType(NewDI->getType(),
- D->getLocation());
+ QualType NewT =
+ SemaRef.CheckNonTypeTemplateParameterType(NewDI, D->getLocation());
if (NewT.isNull())
return nullptr;
+
+ ExpandedParameterPackTypesAsWritten.push_back(NewDI);
ExpandedParameterPackTypes.push_back(NewT);
}
@@ -2136,12 +2136,12 @@ Decl *TemplateDeclInstantiator::VisitNon
if (!NewDI)
return nullptr;
- ExpandedParameterPackTypesAsWritten.push_back(NewDI);
- QualType NewT = SemaRef.CheckNonTypeTemplateParameterType(
- NewDI->getType(),
- D->getLocation());
+ QualType NewT =
+ SemaRef.CheckNonTypeTemplateParameterType(NewDI, D->getLocation());
if (NewT.isNull())
return nullptr;
+
+ ExpandedParameterPackTypesAsWritten.push_back(NewDI);
ExpandedParameterPackTypes.push_back(NewT);
}
@@ -2161,6 +2161,7 @@ Decl *TemplateDeclInstantiator::VisitNon
if (!NewPattern)
return nullptr;
+ SemaRef.CheckNonTypeTemplateParameterType(NewPattern, D->getLocation());
DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(),
NumExpansions);
if (!DI)
@@ -2176,8 +2177,7 @@ Decl *TemplateDeclInstantiator::VisitNon
return nullptr;
// Check that this type is acceptable for a non-type template parameter.
- T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(),
- D->getLocation());
+ T = SemaRef.CheckNonTypeTemplateParameterType(DI, D->getLocation());
if (T.isNull()) {
T = SemaRef.Context.IntTy;
Invalid = true;
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=290660&r1=290659&r2=290660&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Dec 28 00:27:18 2016
@@ -1534,14 +1534,7 @@ static QualType ConvertDeclSpecToType(Ty
// template type parameter.
Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);
} else {
- // If auto appears in the declaration of a template parameter, treat
- // the parameter as type-dependent.
- bool IsDependent =
- S.getLangOpts().CPlusPlus1z &&
- declarator.getContext() == Declarator::TemplateParamContext;
- Result = Context.getAutoType(QualType(),
- AutoTypeKeyword::Auto,
- IsDependent);
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
}
break;
Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp?rev=290660&r1=290659&r2=290660&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp Wed Dec 28 00:27:18 2016
@@ -307,3 +307,24 @@ namespace Auto {
static_assert(nth_element_v<2, value_list<'a', 27U, false>> == false, "value mismatch");
}
}
+
+namespace Nested {
+ template<typename T> struct A {
+ template<auto X> struct B;
+ template<auto *P> struct B<P>;
+ template<auto **P> struct B<P> { using pointee = decltype(+**P); };
+ template<auto (*P)(T)> struct B<P> { using param = T; };
+ template<typename U, auto (*P)(T, U)> struct B<P> { using param2 = U; };
+ };
+
+ using Int = int;
+
+ int *n;
+ using Int = A<int>::B<&n>::pointee;
+
+ void f(int);
+ using Int = A<int>::B<&f>::param;
+
+ void g(int, int);
+ using Int = A<int>::B<&g>::param2;
+}
More information about the cfe-commits
mailing list