diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 33 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 83 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 14 |
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); } } } |