summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Lex/PPMacroExpansion.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp33
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp83
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp4
-rw-r--r--clang/lib/Sema/SemaType.cpp14
5 files changed, 107 insertions, 29 deletions
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index d133bd30cf9..1be1801ac2f 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1202,6 +1202,8 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
.Case("cxx_relaxed_constexpr", LangOpts.CPlusPlus14)
.Case("cxx_return_type_deduction", LangOpts.CPlusPlus14)
.Case("cxx_variable_templates", LangOpts.CPlusPlus14)
+ // C++1z features
+ .Case("cxx_template_auto", LangOpts.CPlusPlus1z)
// C++ TSes
//.Case("cxx_runtime_arrays", LangOpts.CPlusPlusTSArrays)
//.Case("cxx_concepts", LangOpts.CPlusPlusTSConcepts)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index bef36206e09..b1bb97b7586 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -730,7 +730,13 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
T->isNullPtrType() ||
// If T is a dependent type, we can't do the check now, so we
// assume that it is well-formed.
- T->isDependentType()) {
+ 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();
@@ -4975,6 +4981,29 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
CheckTemplateArgumentKind CTAK) {
SourceLocation StartLoc = Arg->getLocStart();
+ // If the parameter type somehow involves auto, deduce the type now.
+ if (getLangOpts().CPlusPlus1z && ParamType->isUndeducedType()) {
+ if (DeduceAutoType(
+ Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()),
+ Arg, ParamType) == DAR_Failed) {
+ Diag(Arg->getExprLoc(),
+ diag::err_non_type_template_parm_type_deduction_failure)
+ << Param->getDeclName() << Param->getType() << Arg->getType()
+ << Arg->getSourceRange();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return ExprError();
+ }
+ // CheckNonTypeTemplateParameterType will produce a diagnostic if there's
+ // an error. The error message normally references the parameter
+ // declaration, but here we'll pass the argument location because that's
+ // where the parameter type is deduced.
+ ParamType = CheckNonTypeTemplateParameterType(ParamType, Arg->getExprLoc());
+ if (ParamType.isNull()) {
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return ExprError();
+ }
+ }
+
// If either the parameter has a dependent type or the argument is
// type-dependent, there's nothing we can check now.
if (ParamType->isDependentType() || Arg->isTypeDependent()) {
@@ -7255,7 +7284,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
if (InstantiationFunction->isDeleted()) {
assert(InstantiationFunction->getCanonicalDecl() ==
InstantiationFunction);
- InstantiationFunction->setDeletedAsWritten(false);
+ InstantiationFunction->setDeletedAsWritten(false);
}
}
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 2311b2b7447..4f76a029dcd 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -100,7 +100,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
SmallVectorImpl<DeducedTemplateArgument> &
Deduced,
unsigned TDF,
- bool PartialOrdering = false);
+ bool PartialOrdering = false,
+ bool DeducedFromArrayBound = false);
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
@@ -167,6 +168,12 @@ checkDeducedTemplateArguments(ASTContext &Context,
Context.hasSameType(X.getAsType(), Y.getAsType()))
return X;
+ // If one of the two arguments was deduced from an array bound, the other
+ // supersedes it.
+ if (X.wasDeducedFromArrayBound() != Y.wasDeducedFromArrayBound())
+ return X.wasDeducedFromArrayBound() ? Y : X;
+
+ // The arguments are not compatible.
return DeducedTemplateArgument();
case TemplateArgument::Integral:
@@ -287,7 +294,8 @@ checkDeducedTemplateArguments(ASTContext &Context,
/// \brief Deduce the value of the given non-type template parameter
/// from the given integral constant.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
- Sema &S, NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value,
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value,
QualType ValueType, bool DeducedFromArrayBound, TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
@@ -306,13 +314,20 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
}
Deduced[NTTP->getIndex()] = Result;
- return Sema::TDK_Success;
+ return S.getLangOpts().CPlusPlus1z
+ ? DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, NTTP->getType(), ValueType, Info, Deduced,
+ TDF_ParamWithReferenceType | TDF_SkipNonDependent,
+ /*PartialOrdering=*/false,
+ /*ArrayBound=*/DeducedFromArrayBound)
+ : Sema::TDK_Success;
}
/// \brief Deduce the value of the given non-type template parameter
/// from the given null pointer template argument type.
static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
- Sema &S, NonTypeTemplateParmDecl *NTTP, QualType NullPtrType,
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, QualType NullPtrType,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
Expr *Value =
@@ -332,7 +347,11 @@ static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
}
Deduced[NTTP->getIndex()] = Result;
- return Sema::TDK_Success;
+ return S.getLangOpts().CPlusPlus1z
+ ? DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, NTTP->getType(), Value->getType(), Info,
+ Deduced, TDF_ParamWithReferenceType | TDF_SkipNonDependent)
+ : Sema::TDK_Success;
}
/// \brief Deduce the value of the given non-type template parameter
@@ -341,6 +360,7 @@ static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S,
+ TemplateParameterList *TemplateParams,
NonTypeTemplateParmDecl *NTTP,
Expr *Value,
TemplateDeductionInfo &Info,
@@ -363,7 +383,11 @@ DeduceNonTypeTemplateArgument(Sema &S,
}
Deduced[NTTP->getIndex()] = Result;
- return Sema::TDK_Success;
+ return S.getLangOpts().CPlusPlus1z
+ ? DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, NTTP->getType(), Value->getType(), Info,
+ Deduced, TDF_ParamWithReferenceType | TDF_SkipNonDependent)
+ : Sema::TDK_Success;
}
/// \brief Deduce the value of the given non-type template parameter
@@ -372,8 +396,9 @@ DeduceNonTypeTemplateArgument(Sema &S,
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S,
+ TemplateParameterList *TemplateParams,
NonTypeTemplateParmDecl *NTTP,
- ValueDecl *D,
+ ValueDecl *D, QualType T,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
@@ -393,7 +418,11 @@ DeduceNonTypeTemplateArgument(Sema &S,
}
Deduced[NTTP->getIndex()] = Result;
- return Sema::TDK_Success;
+ return S.getLangOpts().CPlusPlus1z
+ ? DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, NTTP->getType(), T, Info, Deduced,
+ TDF_ParamWithReferenceType | TDF_SkipNonDependent)
+ : Sema::TDK_Success;
}
static Sema::TemplateDeductionResult
@@ -968,7 +997,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
- bool PartialOrdering) {
+ bool PartialOrdering,
+ bool DeducedFromArrayBound) {
// We only want to look at the canonical types, since typedefs and
// sugar are not part of template argument deduction.
QualType Param = S.Context.getCanonicalType(ParamIn);
@@ -1152,7 +1182,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (RecanonicalizeArg)
DeducedType = S.Context.getCanonicalType(DeducedType);
- DeducedTemplateArgument NewDeduced(DeducedType);
+ DeducedTemplateArgument NewDeduced(DeducedType, DeducedFromArrayBound);
DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
Deduced[Index],
NewDeduced);
@@ -1374,7 +1404,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (const ConstantArrayType *ConstantArrayArg
= dyn_cast<ConstantArrayType>(ArrayArg)) {
llvm::APSInt Size(ConstantArrayArg->getSize());
- return DeduceNonTypeTemplateArgument(S, NTTP, Size,
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, Size,
S.Context.getSizeType(),
/*ArrayBound=*/true,
Info, Deduced);
@@ -1382,7 +1412,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (const DependentSizedArrayType *DependentArrayArg
= dyn_cast<DependentSizedArrayType>(ArrayArg))
if (DependentArrayArg->getSizeExpr())
- return DeduceNonTypeTemplateArgument(S, NTTP,
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
DependentArrayArg->getSizeExpr(),
Info, Deduced);
@@ -1654,8 +1684,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
ArgSize = VectorArg->getNumElements();
- return DeduceNonTypeTemplateArgument(S, NTTP, ArgSize, S.Context.IntTy,
- false, Info, Deduced);
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize,
+ S.Context.IntTy, false, Info, Deduced);
}
if (const DependentSizedExtVectorType *VectorArg
@@ -1674,7 +1704,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (!NTTP)
return Sema::TDK_Success;
- return DeduceNonTypeTemplateArgument(S, NTTP, VectorArg->getSizeExpr(),
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ VectorArg->getSizeExpr(),
Info, Deduced);
}
@@ -1779,19 +1810,22 @@ DeduceTemplateArguments(Sema &S,
if (NonTypeTemplateParmDecl *NTTP
= getDeducedParameterFromExpr(Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
- return DeduceNonTypeTemplateArgument(S, NTTP,
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
Arg.getAsIntegral(),
Arg.getIntegralType(),
/*ArrayBound=*/false,
Info, Deduced);
if (Arg.getKind() == TemplateArgument::NullPtr)
- return DeduceNullPtrTemplateArgument(S, NTTP, Arg.getNullPtrType(),
+ return DeduceNullPtrTemplateArgument(S, TemplateParams, NTTP,
+ Arg.getNullPtrType(),
Info, Deduced);
if (Arg.getKind() == TemplateArgument::Expression)
- return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),
- Info, Deduced);
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ Arg.getAsExpr(), Info, Deduced);
if (Arg.getKind() == TemplateArgument::Declaration)
- return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ Arg.getAsDecl(),
+ Arg.getParamTypeForDecl(),
Info, Deduced);
Info.FirstArg = Param;
@@ -3280,7 +3314,7 @@ DeduceFromInitializerList(Sema &S, TemplateParameterList *TemplateParams,
ILE->getNumInits());
Result = DeduceNonTypeTemplateArgument(
- S, NTTP, llvm::APSInt(Size), NTTP->getType(),
+ S, TemplateParams, NTTP, llvm::APSInt(Size), NTTP->getType(),
/*ArrayBound=*/true, Info, Deduced);
}
}
@@ -4700,6 +4734,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
if (NTTP->getDepth() == Depth)
Used[NTTP->getIndex()] = true;
+
+ // In C++1z mode, additional arguments may be deduced from the type of a
+ // non-type argument.
+ if (Ctx.getLangOpts().CPlusPlus1z)
+ MarkUsedTemplateParameters(Ctx, NTTP->getType(), OnlyDeduced, Depth, Used);
}
/// \brief Mark the template parameters that are used by the given
@@ -4946,7 +4985,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
case Type::UnaryTransform:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
- cast<UnaryTransformType>(T)->getUnderlyingType(),
+ cast<UnaryTransformType>(T)->getUnderlyingType(),
OnlyDeduced, Depth, Used);
break;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 50663f9f4ba..b715c13b077 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1179,8 +1179,8 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
cast<PackExpansionType>(parm->getType())->getPattern(),
TemplateArgs, loc, parm->getDeclName());
} else {
- type = SemaRef.SubstType(parm->getType(), TemplateArgs,
- loc, parm->getDeclName());
+ type = SemaRef.SubstType(VD ? arg.getParamTypeForDecl() : arg.getNullPtrType(),
+ TemplateArgs, loc, parm->getDeclName());
}
assert(!type.isNull() && "type substitution failed for param type");
assert(!type->isDependentType() && "param type still dependent");
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index dd833d72217..b0f18fd1bdc 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1582,7 +1582,14 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// template type parameter.
Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);
} else {
- Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
+ // 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);
}
break;
@@ -2858,7 +2865,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 7; // Exception declaration
break;
case Declarator::TemplateParamContext:
- Error = 8; // Template parameter
+ if (!SemaRef.getLangOpts().CPlusPlus1z)
+ Error = 8; // Template parameter
break;
case Declarator::BlockLiteralContext:
Error = 9; // Block literal
@@ -5540,7 +5548,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
if (Class->isArcWeakrefUnavailable()) {
S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
S.Diag(ObjT->getInterfaceDecl()->getLocation(),
- diag::note_class_declared);
+ diag::note_class_declared);
}
}
}
OpenPOWER on IntegriCloud