diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /clang/lib/Sema/SemaTemplate.cpp | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) | |
download | src-cfca06d7963fa0909f90483b42a6d7d194d01e08.tar.gz src-cfca06d7963fa0909f90483b42a6d7d194d01e08.zip |
Vendor import of llvm-project master 2e10b7a39b9, the last commit beforevendor/llvm-project/llvmorg-11-init-20887-g2e10b7a39b9vendor/llvm-project/master
the llvmorg-12-init tag, from which release/11.x was branched.
Notes
Notes:
svn path=/vendor/llvm-project/master/; revision=363578
svn path=/vendor/llvm-project/llvmorg-11-init-20887-g2e10b7a39b9/; revision=363579; tag=vendor/llvm-project/llvmorg-11-init-20887-g2e10b7a39b9
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 888 |
1 files changed, 562 insertions, 326 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 1184446796eb..c05ed0b14e3e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -46,6 +46,47 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps, return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc()); } +unsigned Sema::getTemplateDepth(Scope *S) const { + unsigned Depth = 0; + + // Each template parameter scope represents one level of template parameter + // depth. + for (Scope *TempParamScope = S->getTemplateParamParent(); TempParamScope; + TempParamScope = TempParamScope->getParent()->getTemplateParamParent()) { + ++Depth; + } + + // Note that there are template parameters with the given depth. + auto ParamsAtDepth = [&](unsigned D) { Depth = std::max(Depth, D + 1); }; + + // Look for parameters of an enclosing generic lambda. We don't create a + // template parameter scope for these. + for (FunctionScopeInfo *FSI : getFunctionScopes()) { + if (auto *LSI = dyn_cast<LambdaScopeInfo>(FSI)) { + if (!LSI->TemplateParams.empty()) { + ParamsAtDepth(LSI->AutoTemplateParameterDepth); + break; + } + if (LSI->GLTemplateParameterList) { + ParamsAtDepth(LSI->GLTemplateParameterList->getDepth()); + break; + } + } + } + + // Look for parameters of an enclosing terse function template. We don't + // create a template parameter scope for these either. + for (const InventedTemplateParameterInfo &Info : + getInventedParameterInfos()) { + if (!Info.TemplateParams.empty()) { + ParamsAtDepth(Info.AutoTemplateParameterDepth); + break; + } + } + + return Depth; +} + /// \brief Determine whether the declaration found is acceptable as the name /// of a template and, if so, return that template declaration. Otherwise, /// returns null. @@ -132,7 +173,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S, ParsedType ObjectTypePtr, bool EnteringContext, TemplateTy &TemplateResult, - bool &MemberOfUnknownSpecialization) { + bool &MemberOfUnknownSpecialization, + bool Disambiguation) { assert(getLangOpts().CPlusPlus && "No template names in C!"); DeclarationName TName; @@ -162,7 +204,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S, LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName); if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext, MemberOfUnknownSpecialization, SourceLocation(), - &AssumedTemplate)) + &AssumedTemplate, + /*AllowTypoCorrection=*/!Disambiguation)) return TNK_Non_template; if (AssumedTemplate != AssumedTemplateKind::None) { @@ -328,11 +371,15 @@ bool Sema::LookupTemplateName(LookupResult &Found, QualType ObjectType, bool EnteringContext, bool &MemberOfUnknownSpecialization, - SourceLocation TemplateKWLoc, - AssumedTemplateKind *ATK) { + RequiredTemplateKind RequiredTemplate, + AssumedTemplateKind *ATK, + bool AllowTypoCorrection) { if (ATK) *ATK = AssumedTemplateKind::None; + if (SS.isInvalid()) + return true; + Found.setTemplateNameLookup(true); // Determine where to perform name lookup @@ -342,7 +389,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, if (!ObjectType.isNull()) { // This nested-name-specifier occurs in a member access expression, e.g., // x->B::f, and we are looking into the type of the object. - assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); + assert(SS.isEmpty() && "ObjectType and scope specifier cannot coexist"); LookupCtx = computeDeclContext(ObjectType); IsDependent = !LookupCtx && ObjectType->isDependentType(); assert((IsDependent || !ObjectType->isIncompleteType() || @@ -368,11 +415,11 @@ bool Sema::LookupTemplateName(LookupResult &Found, Found.clear(); return false; } - } else if (SS.isSet()) { + } else if (SS.isNotEmpty()) { // This nested-name-specifier occurs after another nested-name-specifier, // so long into the context associated with the prior nested-name-specifier. LookupCtx = computeDeclContext(SS, EnteringContext); - IsDependent = !LookupCtx; + IsDependent = !LookupCtx && isDependentScopeSpecifier(SS); // The declaration context must be complete. if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx)) @@ -399,7 +446,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, IsDependent |= Found.wasNotFoundInCurrentInstantiation(); } - if (!SS.isSet() && (ObjectType.isNull() || Found.empty())) { + if (SS.isEmpty() && (ObjectType.isNull() || Found.empty())) { // C++ [basic.lookup.classref]p1: // In a class member access expression (5.2.5), if the . or -> token is // immediately followed by an identifier followed by a <, the @@ -426,7 +473,8 @@ bool Sema::LookupTemplateName(LookupResult &Found, if (Found.isAmbiguous()) return false; - if (ATK && !SS.isSet() && ObjectType.isNull() && TemplateKWLoc.isInvalid()) { + if (ATK && SS.isEmpty() && ObjectType.isNull() && + !RequiredTemplate.hasTemplateKeyword()) { // C++2a [temp.names]p2: // A name is also considered to refer to a template if it is an // unqualified-id followed by a < and name lookup finds either one or more @@ -436,7 +484,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, // all language modes, and diagnose the empty lookup in ActOnCallExpr if we // successfully form a call to an undeclared template-id. bool AllFunctions = - getLangOpts().CPlusPlus2a && + getLangOpts().CPlusPlus20 && std::all_of(Found.begin(), Found.end(), [](NamedDecl *ND) { return isa<FunctionDecl>(ND->getUnderlyingDecl()); }); @@ -452,8 +500,9 @@ bool Sema::LookupTemplateName(LookupResult &Found, } } - if (Found.empty() && !IsDependent) { - // If we did not find any names, attempt to correct any typos. + if (Found.empty() && !IsDependent && AllowTypoCorrection) { + // If we did not find any names, and this is not a disambiguation, attempt + // to correct any typos. DeclarationName Name = Found.getLookupName(); Found.clear(); // Simple filter callback that, for keywords, only accepts the C++ *_cast @@ -497,9 +546,11 @@ bool Sema::LookupTemplateName(LookupResult &Found, // If a 'template' keyword was used, a lookup that finds only non-template // names is an error. - if (ExampleLookupResult && TemplateKWLoc.isValid()) { + if (ExampleLookupResult && RequiredTemplate) { Diag(Found.getNameLoc(), diag::err_template_kw_refers_to_non_template) - << Found.getLookupName() << SS.getRange(); + << Found.getLookupName() << SS.getRange() + << RequiredTemplate.hasTemplateKeyword() + << RequiredTemplate.getTemplateKeywordLoc(); Diag(ExampleLookupResult->getUnderlyingDecl()->getLocation(), diag::note_template_kw_refers_to_non_template) << Found.getLookupName(); @@ -1050,7 +1101,8 @@ makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) { return TemplateArgs; } -bool Sema::ActOnTypeConstraint(TemplateIdAnnotation *TypeConstr, +bool Sema::ActOnTypeConstraint(const CXXScopeSpec &SS, + TemplateIdAnnotation *TypeConstr, TemplateTypeParmDecl *ConstrainedParameter, SourceLocation EllipsisLoc) { ConceptDecl *CD = @@ -1080,14 +1132,57 @@ bool Sema::ActOnTypeConstraint(TemplateIdAnnotation *TypeConstr, makeTemplateArgumentListInfo(*this, *TypeConstr); } return AttachTypeConstraint( - TypeConstr->SS.isSet() ? TypeConstr->SS.getWithLocInContext(Context) : - NestedNameSpecifierLoc(), + SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc(), DeclarationNameInfo(DeclarationName(TypeConstr->Name), TypeConstr->TemplateNameLoc), CD, TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr, ConstrainedParameter, EllipsisLoc); } +template<typename ArgumentLocAppender> +static ExprResult formImmediatelyDeclaredConstraint( + Sema &S, NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo, + ConceptDecl *NamedConcept, SourceLocation LAngleLoc, + SourceLocation RAngleLoc, QualType ConstrainedType, + SourceLocation ParamNameLoc, ArgumentLocAppender Appender, + SourceLocation EllipsisLoc) { + + TemplateArgumentListInfo ConstraintArgs; + ConstraintArgs.addArgument( + S.getTrivialTemplateArgumentLoc(TemplateArgument(ConstrainedType), + /*NTTPType=*/QualType(), ParamNameLoc)); + + ConstraintArgs.setRAngleLoc(RAngleLoc); + ConstraintArgs.setLAngleLoc(LAngleLoc); + Appender(ConstraintArgs); + + // C++2a [temp.param]p4: + // [...] This constraint-expression E is called the immediately-declared + // constraint of T. [...] + CXXScopeSpec SS; + SS.Adopt(NS); + ExprResult ImmediatelyDeclaredConstraint = S.CheckConceptTemplateId( + SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo, + /*FoundDecl=*/NamedConcept, NamedConcept, &ConstraintArgs); + if (ImmediatelyDeclaredConstraint.isInvalid() || !EllipsisLoc.isValid()) + return ImmediatelyDeclaredConstraint; + + // C++2a [temp.param]p4: + // [...] If T is not a pack, then E is E', otherwise E is (E' && ...). + // + // We have the following case: + // + // template<typename T> concept C1 = true; + // template<C1... T> struct s1; + // + // The constraint: (C1<T> && ...) + return S.BuildCXXFoldExpr(/*LParenLoc=*/SourceLocation(), + ImmediatelyDeclaredConstraint.get(), BO_LAnd, + EllipsisLoc, /*RHS=*/nullptr, + /*RParenLoc=*/SourceLocation(), + /*NumExpansions=*/None); +} + /// Attach a type-constraint to a template parameter. /// \returns true if an error occured. This can happen if the /// immediately-declared constraint could not be formed (e.g. incorrect number @@ -1106,51 +1201,21 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS, *TemplateArgs) : nullptr; QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0); - TemplateArgumentListInfo ConstraintArgs; - ConstraintArgs.addArgument( - TemplateArgumentLoc( - TemplateArgument(ParamAsArgument), - TemplateArgumentLocInfo( - Context.getTrivialTypeSourceInfo(ParamAsArgument, - ConstrainedParameter->getLocation())))); - if (TemplateArgs) { - ConstraintArgs.setRAngleLoc(TemplateArgs->getRAngleLoc()); - ConstraintArgs.setLAngleLoc(TemplateArgs->getLAngleLoc()); - for (const TemplateArgumentLoc &ArgLoc : TemplateArgs->arguments()) - ConstraintArgs.addArgument(ArgLoc); - } - // C++2a [temp.param]p4: - // [...] This constraint-expression E is called the immediately-declared - // constraint of T. [...] - CXXScopeSpec SS; - SS.Adopt(NS); - ExprResult ImmediatelyDeclaredConstraint = CheckConceptTemplateId(SS, - /*TemplateKWLoc=*/SourceLocation(), NameInfo, /*FoundDecl=*/NamedConcept, - NamedConcept, &ConstraintArgs); + ExprResult ImmediatelyDeclaredConstraint = + formImmediatelyDeclaredConstraint( + *this, NS, NameInfo, NamedConcept, + TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(), + TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(), + ParamAsArgument, ConstrainedParameter->getLocation(), + [&] (TemplateArgumentListInfo &ConstraintArgs) { + if (TemplateArgs) + for (const auto &ArgLoc : TemplateArgs->arguments()) + ConstraintArgs.addArgument(ArgLoc); + }, EllipsisLoc); if (ImmediatelyDeclaredConstraint.isInvalid()) return true; - if (ConstrainedParameter->isParameterPack()) { - // C++2a [temp.param]p4: - // [...] If T is not a pack, then E is E', otherwise E is (E' && ...). - // - // We have the following case: - // - // template<typename T> concept C1 = true; - // template<C1... T> struct s1; - // - // The constraint: (C1<T> && ...) - ImmediatelyDeclaredConstraint = - BuildCXXFoldExpr(/*LParenLoc=*/SourceLocation(), - ImmediatelyDeclaredConstraint.get(), BO_LAnd, - EllipsisLoc, /*RHS=*/nullptr, - /*RParenLoc=*/SourceLocation(), - /*NumExpansions=*/None).get(); - if (ImmediatelyDeclaredConstraint.isInvalid()) - return true; - } - ConstrainedParameter->setTypeConstraint(NS, NameInfo, /*FoundDecl=*/NamedConcept, NamedConcept, ArgsAsWritten, @@ -1158,6 +1223,38 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS, return false; } +bool Sema::AttachTypeConstraint(AutoTypeLoc TL, NonTypeTemplateParmDecl *NTTP, + SourceLocation EllipsisLoc) { + if (NTTP->getType() != TL.getType() || + TL.getAutoKeyword() != AutoTypeKeyword::Auto) { + Diag(NTTP->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), + diag::err_unsupported_placeholder_constraint) + << NTTP->getTypeSourceInfo()->getTypeLoc().getSourceRange(); + return true; + } + // FIXME: Concepts: This should be the type of the placeholder, but this is + // unclear in the wording right now. + DeclRefExpr *Ref = BuildDeclRefExpr(NTTP, NTTP->getType(), VK_RValue, + NTTP->getLocation()); + if (!Ref) + return true; + ExprResult ImmediatelyDeclaredConstraint = + formImmediatelyDeclaredConstraint( + *this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(), + TL.getNamedConcept(), TL.getLAngleLoc(), TL.getRAngleLoc(), + BuildDecltypeType(Ref, NTTP->getLocation()), NTTP->getLocation(), + [&] (TemplateArgumentListInfo &ConstraintArgs) { + for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I) + ConstraintArgs.addArgument(TL.getArgLoc(I)); + }, EllipsisLoc); + if (ImmediatelyDeclaredConstraint.isInvalid() || + !ImmediatelyDeclaredConstraint.isUsable()) + return true; + + NTTP->setPlaceholderTypeConstraint(ImmediatelyDeclaredConstraint.get()); + return false; +} + /// Check that the type of a non-type template parameter is /// well-formed. /// @@ -1242,11 +1339,11 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, // Check that we have valid decl-specifiers specified. auto CheckValidDeclSpecifiers = [this, &D] { // C++ [temp.param] - // p1 + // p1 // template-parameter: // ... // parameter-declaration - // p2 + // p2 // ... A storage class shall not be specified in a template-parameter // declaration. // [dcl.typedef]p1: @@ -1319,6 +1416,11 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, TInfo); Param->setAccess(AS_public); + if (AutoTypeLoc TL = TInfo->getTypeLoc().getContainedAutoTypeLoc()) + if (TL.isConstrained()) + if (AttachTypeConstraint(TL, Param, D.getEllipsisLoc())) + Invalid = true; + if (Invalid) Param->setInvalidDecl(); @@ -1844,16 +1946,46 @@ namespace { /// constructor to a deduction guide. class ExtractTypeForDeductionGuide : public TreeTransform<ExtractTypeForDeductionGuide> { + llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs; + public: typedef TreeTransform<ExtractTypeForDeductionGuide> Base; - ExtractTypeForDeductionGuide(Sema &SemaRef) : Base(SemaRef) {} + ExtractTypeForDeductionGuide( + Sema &SemaRef, + llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) + : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs) {} TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); } QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { - return TransformType( - TLB, - TL.getTypedefNameDecl()->getTypeSourceInfo()->getTypeLoc()); + ASTContext &Context = SemaRef.getASTContext(); + TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl(); + TypeLocBuilder InnerTLB; + QualType Transformed = + TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc()); + TypeSourceInfo *TSI = + TransformType(InnerTLB.getTypeSourceInfo(Context, Transformed)); + + TypedefNameDecl *Decl = nullptr; + + if (isa<TypeAliasDecl>(OrigDecl)) + Decl = TypeAliasDecl::Create( + Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), + OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); + else { + assert(isa<TypedefDecl>(OrigDecl) && "Not a Type alias or typedef"); + Decl = TypedefDecl::Create( + Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), + OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); + } + + MaterializedTypedefs.push_back(Decl); + + QualType TDTy = Context.getTypedefType(Decl); + TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy); + TypedefTL.setNameLoc(TL.getNameLoc()); + + return TDTy; } }; @@ -1905,6 +2037,7 @@ struct ConvertConstructorToDeductionGuideTransform { // a list of substituted template arguments as we go. for (NamedDecl *Param : *InnerParams) { MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); Args.addOuterTemplateArguments(SubstArgs); Args.addOuterRetainedLevel(); NamedDecl *NewParam = transformTemplateParameter(Param, Args); @@ -1924,6 +2057,7 @@ struct ConvertConstructorToDeductionGuideTransform { // substitute references to the old parameters into references to the // new ones. MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); if (FTD) { Args.addOuterTemplateArguments(SubstArgs); Args.addOuterRetainedLevel(); @@ -1938,14 +2072,16 @@ struct ConvertConstructorToDeductionGuideTransform { // new ones. TypeLocBuilder TLB; SmallVector<ParmVarDecl*, 8> Params; - QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args); + SmallVector<TypedefNameDecl *, 4> MaterializedTypedefs; + QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args, + MaterializedTypedefs); if (NewType.isNull()) return nullptr; TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType); return buildDeductionGuide(TemplateParams, CD->getExplicitSpecifier(), NewTInfo, CD->getBeginLoc(), CD->getLocation(), - CD->getEndLoc()); + CD->getEndLoc(), MaterializedTypedefs); } /// Build a deduction guide with the specified parameter types. @@ -1996,12 +2132,14 @@ private: if (const auto *TC = TTP->getTypeConstraint()) { TemplateArgumentListInfo TransformedArgs; const auto *ArgsAsWritten = TC->getTemplateArgsAsWritten(); - if (SemaRef.Subst(ArgsAsWritten->getTemplateArgs(), + if (!ArgsAsWritten || + SemaRef.Subst(ArgsAsWritten->getTemplateArgs(), ArgsAsWritten->NumTemplateArgs, TransformedArgs, Args)) SemaRef.AttachTypeConstraint( TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(), - TC->getNamedConcept(), &TransformedArgs, NewTTP, + TC->getNamedConcept(), ArgsAsWritten ? &TransformedArgs : nullptr, + NewTTP, NewTTP->isParameterPack() ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) ->getEllipsisLoc() @@ -2038,16 +2176,18 @@ private: return NewParam; } - QualType transformFunctionProtoType(TypeLocBuilder &TLB, - FunctionProtoTypeLoc TL, - SmallVectorImpl<ParmVarDecl*> &Params, - MultiLevelTemplateArgumentList &Args) { + QualType transformFunctionProtoType( + TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, + SmallVectorImpl<ParmVarDecl *> &Params, + MultiLevelTemplateArgumentList &Args, + SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) { SmallVector<QualType, 4> ParamTypes; const FunctionProtoType *T = TL.getTypePtr(); // -- The types of the function parameters are those of the constructor. for (auto *OldParam : TL.getParams()) { - ParmVarDecl *NewParam = transformFunctionTypeParam(OldParam, Args); + ParmVarDecl *NewParam = + transformFunctionTypeParam(OldParam, Args, MaterializedTypedefs); if (!NewParam) return QualType(); ParamTypes.push_back(NewParam->getType()); @@ -2089,9 +2229,9 @@ private: return Result; } - ParmVarDecl * - transformFunctionTypeParam(ParmVarDecl *OldParam, - MultiLevelTemplateArgumentList &Args) { + ParmVarDecl *transformFunctionTypeParam( + ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args, + llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) { TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo(); TypeSourceInfo *NewDI; if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) { @@ -2114,15 +2254,22 @@ private: // members of the current instantiations with the definitions of those // typedefs, avoiding triggering instantiation of the deduced type during // deduction. - NewDI = ExtractTypeForDeductionGuide(SemaRef).transform(NewDI); + NewDI = ExtractTypeForDeductionGuide(SemaRef, MaterializedTypedefs) + .transform(NewDI); // Resolving a wording defect, we also inherit default arguments from the // constructor. ExprResult NewDefArg; if (OldParam->hasDefaultArg()) { - NewDefArg = SemaRef.SubstExpr(OldParam->getDefaultArg(), Args); - if (NewDefArg.isInvalid()) - return nullptr; + // We don't care what the value is (we won't use it); just create a + // placeholder to indicate there is a default argument. + QualType ParamTy = NewDI->getType(); + NewDefArg = new (SemaRef.Context) + OpaqueValueExpr(OldParam->getDefaultArg()->getBeginLoc(), + ParamTy.getNonLValueExprType(SemaRef.Context), + ParamTy->isLValueReferenceType() ? VK_LValue : + ParamTy->isRValueReferenceType() ? VK_XValue : + VK_RValue); } ParmVarDecl *NewParam = ParmVarDecl::Create(SemaRef.Context, DC, @@ -2139,10 +2286,11 @@ private: return NewParam; } - NamedDecl *buildDeductionGuide(TemplateParameterList *TemplateParams, - ExplicitSpecifier ES, TypeSourceInfo *TInfo, - SourceLocation LocStart, SourceLocation Loc, - SourceLocation LocEnd) { + FunctionTemplateDecl *buildDeductionGuide( + TemplateParameterList *TemplateParams, ExplicitSpecifier ES, + TypeSourceInfo *TInfo, SourceLocation LocStart, SourceLocation Loc, + SourceLocation LocEnd, + llvm::ArrayRef<TypedefNameDecl *> MaterializedTypedefs = {}) { DeclarationNameInfo Name(DeductionGuideName, Loc); ArrayRef<ParmVarDecl *> Params = TInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(); @@ -2156,6 +2304,8 @@ private: for (auto *Param : Params) Param->setDeclContext(Guide); + for (auto *TD : MaterializedTypedefs) + TD->setDeclContext(Guide); auto *GuideTemplate = FunctionTemplateDecl::Create( SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide); @@ -2762,7 +2912,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId, ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend, - bool &IsMemberSpecialization, bool &Invalid) { + bool &IsMemberSpecialization, bool &Invalid, bool SuppressDiagnostic) { IsMemberSpecialization = false; Invalid = false; @@ -2870,8 +3020,9 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( auto CheckExplicitSpecialization = [&](SourceRange Range, bool Recovery) { if (SawNonEmptyTemplateParameterList) { - Diag(DeclLoc, diag::err_specialize_member_of_template) - << !Recovery << Range; + if (!SuppressDiagnostic) + Diag(DeclLoc, diag::err_specialize_member_of_template) + << !Recovery << Range; Invalid = true; IsMemberSpecialization = false; return true; @@ -2892,9 +3043,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( else ExpectedTemplateLoc = DeclStartLoc; - Diag(DeclLoc, diag::err_template_spec_needs_header) - << Range - << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> "); + if (!SuppressDiagnostic) + Diag(DeclLoc, diag::err_template_spec_needs_header) + << Range + << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> "); return false; }; @@ -2984,12 +3136,13 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( if (ParamIdx < ParamLists.size()) { if (ParamLists[ParamIdx]->size() > 0) { // The header has template parameters when it shouldn't. Complain. - Diag(ParamLists[ParamIdx]->getTemplateLoc(), - diag::err_template_param_list_matches_nontemplate) - << T - << SourceRange(ParamLists[ParamIdx]->getLAngleLoc(), - ParamLists[ParamIdx]->getRAngleLoc()) - << getRangeOfTypeInNestedNameSpecifier(Context, T, SS); + if (!SuppressDiagnostic) + Diag(ParamLists[ParamIdx]->getTemplateLoc(), + diag::err_template_param_list_matches_nontemplate) + << T + << SourceRange(ParamLists[ParamIdx]->getLAngleLoc(), + ParamLists[ParamIdx]->getRAngleLoc()) + << getRangeOfTypeInNestedNameSpecifier(Context, T, SS); Invalid = true; return nullptr; } @@ -3025,7 +3178,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( if (ExpectedTemplateParams && !TemplateParameterListsAreEqual(ParamLists[ParamIdx], ExpectedTemplateParams, - true, TPL_TemplateMatch)) + !SuppressDiagnostic, TPL_TemplateMatch)) Invalid = true; if (!Invalid && @@ -3037,9 +3190,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( continue; } - Diag(DeclLoc, diag::err_template_spec_needs_template_parameters) - << T - << getRangeOfTypeInNestedNameSpecifier(Context, T, SS); + if (!SuppressDiagnostic) + Diag(DeclLoc, diag::err_template_spec_needs_template_parameters) + << T + << getRangeOfTypeInNestedNameSpecifier(Context, T, SS); Invalid = true; continue; } @@ -3075,16 +3229,18 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( AllExplicitSpecHeaders = false; } - Diag(ParamLists[ParamIdx]->getTemplateLoc(), - AllExplicitSpecHeaders ? diag::warn_template_spec_extra_headers - : diag::err_template_spec_extra_headers) - << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(), - ParamLists[ParamLists.size() - 2]->getRAngleLoc()); + if (!SuppressDiagnostic) + Diag(ParamLists[ParamIdx]->getTemplateLoc(), + AllExplicitSpecHeaders ? diag::warn_template_spec_extra_headers + : diag::err_template_spec_extra_headers) + << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(), + ParamLists[ParamLists.size() - 2]->getRAngleLoc()); // If there was a specialization somewhere, such that 'template<>' is // not required, and there were any 'template<>' headers, note where the // specialization occurred. - if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader) + if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader && + !SuppressDiagnostic) Diag(ExplicitSpecLoc, diag::note_explicit_template_spec_does_not_need_header) << NestedTypes.back(); @@ -3360,6 +3516,10 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, DTN->getIdentifier(), TemplateArgs); + if (Name.getAsAssumedTemplateName() && + resolveAssumedTemplateNameAsType(/*Scope*/nullptr, Name, TemplateLoc)) + return QualType(); + TemplateDecl *Template = Name.getAsTemplateDecl(); if (!Template || isa<FunctionTemplateDecl>(Template) || isa<VarTemplateDecl>(Template) || isa<ConceptDecl>(Template)) { @@ -3399,9 +3559,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Only substitute for the innermost template argument list. MultiLevelTemplateArgumentList TemplateArgLists; TemplateArgLists.addOuterTemplateArguments(&StackTemplateArgs); - unsigned Depth = AliasTemplate->getTemplateParameters()->getDepth(); - for (unsigned I = 0; I < Depth; ++I) - TemplateArgLists.addOuterTemplateArguments(None); + TemplateArgLists.addOuterRetainedLevels( + AliasTemplate->getTemplateParameters()->getDepth()); LocalInstantiationScope Scope(*this); InstantiatingTemplate Inst(*this, TemplateLoc, Template); @@ -3707,6 +3866,9 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc) { + if (SS.isInvalid()) + return TypeResult(true); + TemplateName Template = TemplateD.get(); // Translate the parser's template argument list in our AST format. @@ -4044,7 +4206,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(), Converted) && - (!Context.getLangOpts().ConceptsTS || + (!Context.getLangOpts().CPlusPlus20 || !TemplateParams->hasAssociatedConstraints())) { // C++ [temp.class.spec]p9b3: // @@ -4510,21 +4672,28 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs); } -/// Form a dependent template name. +/// Form a template name from a name that is syntactically required to name a +/// template, either due to use of the 'template' keyword or because a name in +/// this syntactic context is assumed to name a template (C++ [temp.names]p2-4). +/// +/// This action forms a template name given the name of the template and its +/// optional scope specifier. This is used when the 'template' keyword is used +/// or when the parsing context unambiguously treats a following '<' as +/// introducing a template argument list. Note that this may produce a +/// non-dependent template name if we can perform the lookup now and identify +/// the named template. /// -/// This action forms a dependent template name given the template -/// name and its (presumably dependent) scope specifier. For -/// example, given "MetaFun::template apply", the scope specifier \p -/// SS will be "MetaFun::", \p TemplateKWLoc contains the location +/// For example, given "x.MetaFun::template apply", the scope specifier +/// \p SS will be "MetaFun::", \p TemplateKWLoc contains the location /// of the "template" keyword, and "apply" is the \p Name. -TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, - CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - const UnqualifiedId &Name, - ParsedType ObjectType, - bool EnteringContext, - TemplateTy &Result, - bool AllowInjectedClassName) { +TemplateNameKind Sema::ActOnTemplateName(Scope *S, + CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + const UnqualifiedId &Name, + ParsedType ObjectType, + bool EnteringContext, + TemplateTy &Result, + bool AllowInjectedClassName) { if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent()) Diag(TemplateKWLoc, getLangOpts().CPlusPlus11 ? @@ -4532,95 +4701,115 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, diag::ext_template_outside_of_template) << FixItHint::CreateRemoval(TemplateKWLoc); + if (SS.isInvalid()) + return TNK_Non_template; + + // Figure out where isTemplateName is going to look. DeclContext *LookupCtx = nullptr; - if (SS.isSet()) + if (SS.isNotEmpty()) LookupCtx = computeDeclContext(SS, EnteringContext); - if (!LookupCtx && ObjectType) - LookupCtx = computeDeclContext(ObjectType.get()); - if (LookupCtx) { - // C++0x [temp.names]p5: - // If a name prefixed by the keyword template is not the name of - // a template, the program is ill-formed. [Note: the keyword - // template may not be applied to non-template members of class - // templates. -end note ] [ Note: as is the case with the - // typename prefix, the template prefix is allowed in cases - // where it is not strictly necessary; i.e., when the - // nested-name-specifier or the expression on the left of the -> - // or . is not dependent on a template-parameter, or the use - // does not appear in the scope of a template. -end note] - // - // Note: C++03 was more strict here, because it banned the use of - // the "template" keyword prior to a template-name that was not a - // dependent name. C++ DR468 relaxed this requirement (the - // "template" keyword is now permitted). We follow the C++0x - // rules, even in C++03 mode with a warning, retroactively applying the DR. - bool MemberOfUnknownSpecialization; - TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name, - ObjectType, EnteringContext, Result, - MemberOfUnknownSpecialization); - if (TNK == TNK_Non_template && MemberOfUnknownSpecialization) { - // This is a dependent template. Handle it below. - } else if (TNK == TNK_Non_template) { - // Do the lookup again to determine if this is a "nothing found" case or - // a "not a template" case. FIXME: Refactor isTemplateName so we don't - // need to do this. - DeclarationNameInfo DNI = GetNameFromUnqualifiedId(Name); - LookupResult R(*this, DNI.getName(), Name.getBeginLoc(), - LookupOrdinaryName); - bool MOUS; - if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, - MOUS, TemplateKWLoc) && !R.isAmbiguous()) + else if (ObjectType) + LookupCtx = computeDeclContext(GetTypeFromParser(ObjectType)); + + // C++0x [temp.names]p5: + // If a name prefixed by the keyword template is not the name of + // a template, the program is ill-formed. [Note: the keyword + // template may not be applied to non-template members of class + // templates. -end note ] [ Note: as is the case with the + // typename prefix, the template prefix is allowed in cases + // where it is not strictly necessary; i.e., when the + // nested-name-specifier or the expression on the left of the -> + // or . is not dependent on a template-parameter, or the use + // does not appear in the scope of a template. -end note] + // + // Note: C++03 was more strict here, because it banned the use of + // the "template" keyword prior to a template-name that was not a + // dependent name. C++ DR468 relaxed this requirement (the + // "template" keyword is now permitted). We follow the C++0x + // rules, even in C++03 mode with a warning, retroactively applying the DR. + bool MemberOfUnknownSpecialization; + TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name, + ObjectType, EnteringContext, Result, + MemberOfUnknownSpecialization); + if (TNK != TNK_Non_template) { + // We resolved this to a (non-dependent) template name. Return it. + auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx); + if (!AllowInjectedClassName && SS.isNotEmpty() && LookupRD && + Name.getKind() == UnqualifiedIdKind::IK_Identifier && + Name.Identifier && LookupRD->getIdentifier() == Name.Identifier) { + // C++14 [class.qual]p2: + // In a lookup in which function names are not ignored and the + // nested-name-specifier nominates a class C, if the name specified + // [...] is the injected-class-name of C, [...] the name is instead + // considered to name the constructor + // + // We don't get here if naming the constructor would be valid, so we + // just reject immediately and recover by treating the + // injected-class-name as naming the template. + Diag(Name.getBeginLoc(), + diag::ext_out_of_line_qualified_id_type_names_constructor) + << Name.Identifier + << 0 /*injected-class-name used as template name*/ + << TemplateKWLoc.isValid(); + } + return TNK; + } + + if (!MemberOfUnknownSpecialization) { + // Didn't find a template name, and the lookup wasn't dependent. + // Do the lookup again to determine if this is a "nothing found" case or + // a "not a template" case. FIXME: Refactor isTemplateName so we don't + // need to do this. + DeclarationNameInfo DNI = GetNameFromUnqualifiedId(Name); + LookupResult R(*this, DNI.getName(), Name.getBeginLoc(), + LookupOrdinaryName); + bool MOUS; + // Tell LookupTemplateName that we require a template so that it diagnoses + // cases where it finds a non-template. + RequiredTemplateKind RTK = TemplateKWLoc.isValid() + ? RequiredTemplateKind(TemplateKWLoc) + : TemplateNameIsRequired; + if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, MOUS, + RTK, nullptr, /*AllowTypoCorrection=*/false) && + !R.isAmbiguous()) { + if (LookupCtx) Diag(Name.getBeginLoc(), diag::err_no_member) << DNI.getName() << LookupCtx << SS.getRange(); - return TNK_Non_template; - } else { - // We found something; return it. - auto *LookupRD = dyn_cast<CXXRecordDecl>(LookupCtx); - if (!AllowInjectedClassName && SS.isSet() && LookupRD && - Name.getKind() == UnqualifiedIdKind::IK_Identifier && - Name.Identifier && LookupRD->getIdentifier() == Name.Identifier) { - // C++14 [class.qual]p2: - // In a lookup in which function names are not ignored and the - // nested-name-specifier nominates a class C, if the name specified - // [...] is the injected-class-name of C, [...] the name is instead - // considered to name the constructor - // - // We don't get here if naming the constructor would be valid, so we - // just reject immediately and recover by treating the - // injected-class-name as naming the template. - Diag(Name.getBeginLoc(), - diag::ext_out_of_line_qualified_id_type_names_constructor) - << Name.Identifier - << 0 /*injected-class-name used as template name*/ - << 1 /*'template' keyword was used*/; - } - return TNK; + else + Diag(Name.getBeginLoc(), diag::err_undeclared_use) + << DNI.getName() << SS.getRange(); } + return TNK_Non_template; } NestedNameSpecifier *Qualifier = SS.getScopeRep(); switch (Name.getKind()) { case UnqualifiedIdKind::IK_Identifier: - Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, - Name.Identifier)); + Result = TemplateTy::make( + Context.getDependentTemplateName(Qualifier, Name.Identifier)); return TNK_Dependent_template_name; case UnqualifiedIdKind::IK_OperatorFunctionId: - Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, - Name.OperatorFunctionId.Operator)); + Result = TemplateTy::make(Context.getDependentTemplateName( + Qualifier, Name.OperatorFunctionId.Operator)); return TNK_Function_template; case UnqualifiedIdKind::IK_LiteralOperatorId: - llvm_unreachable("literal operator id cannot have a dependent scope"); + // This is a kind of template name, but can never occur in a dependent + // scope (literal operators can only be declared at namespace scope). + break; default: break; } - Diag(Name.getBeginLoc(), diag::err_template_kw_refers_to_non_template) + // This name cannot possibly name a dependent template. Diagnose this now + // rather than building a dependent template name that can never be valid. + Diag(Name.getBeginLoc(), + diag::err_template_kw_refers_to_dependent_non_template) << GetNameFromUnqualifiedId(Name).getName() << Name.getSourceRange() - << TemplateKWLoc; + << TemplateKWLoc.isValid() << TemplateKWLoc; return TNK_Non_template; } @@ -4655,10 +4844,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, CXXScopeSpec SS; DeclarationNameInfo NameInfo; - if (DeclRefExpr *ArgExpr = dyn_cast<DeclRefExpr>(Arg.getAsExpr())) { - SS.Adopt(ArgExpr->getQualifierLoc()); - NameInfo = ArgExpr->getNameInfo(); - } else if (DependentScopeDeclRefExpr *ArgExpr = + if (DependentScopeDeclRefExpr *ArgExpr = dyn_cast<DependentScopeDeclRefExpr>(Arg.getAsExpr())) { SS.Adopt(ArgExpr->getQualifierLoc()); NameInfo = ArgExpr->getNameInfo(); @@ -4677,6 +4863,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, if (Result.getAsSingle<TypeDecl>() || Result.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) { + assert(SS.getScopeRep() && "dependent scope expr must has a scope!"); // Suggest that the user add 'typename' before the NNS. SourceLocation Loc = AL.getSourceRange().getBegin(); Diag(Loc, getLangOpts().MSVCCompat @@ -5716,6 +5903,11 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentSizedExtVectorType( return Visit(T->getElementType()); } +bool UnnamedLocalNoLinkageFinder::VisitDependentSizedMatrixType( + const DependentSizedMatrixType *T) { + return Visit(T->getElementType()); +} + bool UnnamedLocalNoLinkageFinder::VisitDependentAddressSpaceType( const DependentAddressSpaceType *T) { return Visit(T->getPointeeType()); @@ -5734,6 +5926,11 @@ bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) { return Visit(T->getElementType()); } +bool UnnamedLocalNoLinkageFinder::VisitConstantMatrixType( + const ConstantMatrixType *T) { + return Visit(T->getElementType()); +} + bool UnnamedLocalNoLinkageFinder::VisitFunctionProtoType( const FunctionProtoType* T) { for (const auto &A : T->param_types()) { @@ -5815,7 +6012,9 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentNameType( bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType( const DependentTemplateSpecializationType* T) { - return VisitNestedNameSpecifier(T->getQualifier()); + if (auto *Q = T->getQualifier()) + return VisitNestedNameSpecifier(Q); + return false; } bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType( @@ -5845,6 +6044,15 @@ bool UnnamedLocalNoLinkageFinder::VisitPipeType(const PipeType* T) { return false; } +bool UnnamedLocalNoLinkageFinder::VisitExtIntType(const ExtIntType *T) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitDependentExtIntType( + const DependentExtIntType *T) { + return false; +} + bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { if (Tag->getDeclContext()->isFunctionOrMethod()) { S.Diag(SR.getBegin(), @@ -5869,6 +6077,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( NestedNameSpecifier *NNS) { + assert(NNS); if (NNS->getPrefix() && VisitNestedNameSpecifier(NNS->getPrefix())) return true; @@ -6177,8 +6386,11 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, Arg = subst->getReplacement()->IgnoreImpCasts(); } - DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg); - ValueDecl *Entity = DRE ? DRE->getDecl() : nullptr; + ValueDecl *Entity = nullptr; + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg)) + Entity = DRE->getDecl(); + else if (CXXUuidofExpr *CUE = dyn_cast<CXXUuidofExpr>(Arg)) + Entity = CUE->getGuidDecl(); // If our parameter has pointer type, check for a null template value. if (ParamType->isPointerType() || ParamType->isNullPtrType()) { @@ -6205,16 +6417,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, return false; } - if (isa<CXXUuidofExpr>(Arg)) { - if (CheckTemplateArgumentIsCompatibleWithParameter(S, Param, ParamType, - ArgIn, Arg, ArgType)) - return true; - - Converted = TemplateArgument(ArgIn); - return false; - } - - if (!DRE) { + if (!Entity) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref) << Arg->getSourceRange(); S.Diag(Param->getLocation(), diag::note_template_param_here); @@ -6241,13 +6444,14 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, FunctionDecl *Func = dyn_cast<FunctionDecl>(Entity); VarDecl *Var = dyn_cast<VarDecl>(Entity); + MSGuidDecl *Guid = dyn_cast<MSGuidDecl>(Entity); // A non-type template argument must refer to an object or function. - if (!Func && !Var) { + if (!Func && !Var && !Guid) { // We found something, but we don't know specifically what it is. S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_object_or_func) << Arg->getSourceRange(); - S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here); + S.Diag(Entity->getLocation(), diag::note_template_arg_refers_here); return true; } @@ -6268,30 +6472,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, return true; } - if (Func) { - // If the template parameter has pointer type, the function decays. - if (ParamType->isPointerType() && !AddressTaken) - ArgType = S.Context.getPointerType(Func->getType()); - else if (AddressTaken && ParamType->isReferenceType()) { - // If we originally had an address-of operator, but the - // parameter has reference type, complain and (if things look - // like they will work) drop the address-of operator. - if (!S.Context.hasSameUnqualifiedType(Func->getType(), - ParamType.getNonReferenceType())) { - S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) - << ParamType; - S.Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } - - S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) - << ParamType - << FixItHint::CreateRemoval(AddrOpLoc); - S.Diag(Param->getLocation(), diag::note_template_param_here); - - ArgType = Func->getType(); - } - } else { + if (Var) { // A value of reference type is not an object. if (Var->getType()->isReferenceType()) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_reference_var) @@ -6307,50 +6488,53 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, S.Diag(Var->getLocation(), diag::note_template_arg_refers_here); return true; } + } - // If the template parameter has pointer type, we must have taken - // the address of this object. - if (ParamType->isReferenceType()) { - if (AddressTaken) { - // If we originally had an address-of operator, but the - // parameter has reference type, complain and (if things look - // like they will work) drop the address-of operator. - if (!S.Context.hasSameUnqualifiedType(Var->getType(), - ParamType.getNonReferenceType())) { - S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) - << ParamType; - S.Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } + if (AddressTaken && ParamType->isReferenceType()) { + // If we originally had an address-of operator, but the + // parameter has reference type, complain and (if things look + // like they will work) drop the address-of operator. + if (!S.Context.hasSameUnqualifiedType(Entity->getType(), + ParamType.getNonReferenceType())) { + S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) + << ParamType; + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } - S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) - << ParamType - << FixItHint::CreateRemoval(AddrOpLoc); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) + << ParamType + << FixItHint::CreateRemoval(AddrOpLoc); + S.Diag(Param->getLocation(), diag::note_template_param_here); - ArgType = Var->getType(); - } - } else if (!AddressTaken && ParamType->isPointerType()) { - if (Var->getType()->isArrayType()) { - // Array-to-pointer decay. - ArgType = S.Context.getArrayDecayedType(Var->getType()); - } else { - // If the template parameter has pointer type but the address of - // this object was not taken, complain and (possibly) recover by - // taking the address of the entity. - ArgType = S.Context.getPointerType(Var->getType()); - if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) { - S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) - << ParamType; - S.Diag(Param->getLocation(), diag::note_template_param_here); - return true; - } + ArgType = Entity->getType(); + } + // If the template parameter has pointer type, either we must have taken the + // address or the argument must decay to a pointer. + if (!AddressTaken && ParamType->isPointerType()) { + if (Func) { + // Function-to-pointer decay. + ArgType = S.Context.getPointerType(Func->getType()); + } else if (Entity->getType()->isArrayType()) { + // Array-to-pointer decay. + ArgType = S.Context.getArrayDecayedType(Entity->getType()); + } else { + // If the template parameter has pointer type but the address of + // this object was not taken, complain and (possibly) recover by + // taking the address of the entity. + ArgType = S.Context.getPointerType(Entity->getType()); + if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) - << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&"); - + << ParamType; S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; } + + S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) + << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&"); + + S.Diag(Param->getLocation(), diag::note_template_param_here); } } @@ -6530,7 +6714,12 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, DeductionArg = PE->getPattern(); if (DeduceAutoType( Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()), - DeductionArg, ParamType, Depth) == DAR_Failed) { + DeductionArg, ParamType, Depth, + // We do not check constraints right now because the + // immediately-declared constraint of the auto type is also an + // associated constraint, and will be checked along with the other + // associated constraints after checking the template argument list. + /*IgnoreConstraints=*/true) == DAR_Failed) { Diag(Arg->getExprLoc(), diag::err_non_type_template_parm_type_deduction_failure) << Param->getDeclName() << Param->getType() << Arg->getType() @@ -6670,12 +6859,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // -- a predefined __func__ variable APValue::LValueBase Base = Value.getLValueBase(); auto *VD = const_cast<ValueDecl *>(Base.dyn_cast<const ValueDecl *>()); - if (Base && !VD) { - auto *E = Base.dyn_cast<const Expr *>(); - if (E && isa<CXXUuidofExpr>(E)) { - Converted = TemplateArgument(ArgResult.get()->IgnoreImpCasts()); - break; - } + if (Base && (!VD || isa<LifetimeExtendedTemporaryDecl>(VD))) { Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref) << Arg->getSourceRange(); return ExprError(); @@ -6762,7 +6946,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType IntegerType = ParamType; if (const EnumType *Enum = IntegerType->getAs<EnumType>()) IntegerType = Enum->getDecl()->getIntegerType(); - Value = Value.extOrTrunc(Context.getTypeSize(IntegerType)); + Value = Value.extOrTrunc(IntegerType->isExtIntType() + ? Context.getIntWidth(IntegerType) + : Context.getTypeSize(IntegerType)); Converted = TemplateArgument(Context, Value, Context.getCanonicalType(ParamType)); @@ -6856,7 +7042,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // Coerce the template argument's value to the value it will have // based on the template parameter's type. - unsigned AllowedBits = Context.getTypeSize(IntegerType); + unsigned AllowedBits = IntegerType->isExtIntType() + ? Context.getIntWidth(IntegerType) + : Context.getTypeSize(IntegerType); if (Value.getBitWidth() != AllowedBits) Value = Value.extOrTrunc(AllowedBits); Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType()); @@ -7102,6 +7290,11 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, // [temp.constr.order]. SmallVector<const Expr *, 3> ParamsAC, TemplateAC; Params->getAssociatedConstraints(ParamsAC); + // C++2a[temp.arg.template]p3 + // [...] In this comparison, if P is unconstrained, the constraints on A + // are not considered. + if (ParamsAC.empty()) + return false; Template->getAssociatedConstraints(TemplateAC); bool IsParamAtLeastAsConstrained; if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC, @@ -7872,13 +8065,11 @@ bool Sema::CheckTemplatePartialSpecializationArgs( DeclResult Sema::ActOnClassTemplateSpecialization( Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, - SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId, - const ParsedAttributesView &Attr, + SourceLocation ModulePrivateLoc, CXXScopeSpec &SS, + TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr, MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) { assert(TUK != TUK_Reference && "References are not specializations"); - CXXScopeSpec &SS = TemplateId.SS; - // NOTE: KWLoc is the location of the tag keyword. This will instead // store the location of the outermost template keyword in the declaration. SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0 @@ -8048,7 +8239,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (Context.hasSameType(CanonType, ClassTemplate->getInjectedClassNameSpecialization()) && - (!Context.getLangOpts().ConceptsTS || + (!Context.getLangOpts().CPlusPlus20 || !TemplateParams->hasAssociatedConstraints())) { // C++ [temp.class.spec]p9b3: // @@ -8274,7 +8465,7 @@ Decl *Sema::ActOnConceptDefinition(Scope *S, ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name, TemplateParameterLists.front(), ConstraintExpr); - + if (NewDecl->hasAssociatedConstraints()) { // C++2a [temp.concept]p4: // A concept shall not have associated constraints. @@ -10012,24 +10203,12 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, << FixItHint::CreateRemoval(TypenameLoc); NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); + TypeSourceInfo *TSI = nullptr; QualType T = CheckTypenameType(TypenameLoc.isValid()? ETK_Typename : ETK_None, - TypenameLoc, QualifierLoc, II, IdLoc); + TypenameLoc, QualifierLoc, II, IdLoc, &TSI, + /*DeducedTSTContext=*/true); if (T.isNull()) return true; - - TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - if (isa<DependentNameType>(T)) { - DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>(); - TL.setElaboratedKeywordLoc(TypenameLoc); - TL.setQualifierLoc(QualifierLoc); - TL.setNameLoc(IdLoc); - } else { - ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>(); - TL.setElaboratedKeywordLoc(TypenameLoc); - TL.setQualifierLoc(QualifierLoc); - TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc); - } - return CreateParsedType(T, TSI); } @@ -10166,6 +10345,35 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II, return true; } +QualType +Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, + SourceLocation KeywordLoc, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo &II, + SourceLocation IILoc, + TypeSourceInfo **TSI, + bool DeducedTSTContext) { + QualType T = CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, II, IILoc, + DeducedTSTContext); + if (T.isNull()) + return QualType(); + + *TSI = Context.CreateTypeSourceInfo(T); + if (isa<DependentNameType>(T)) { + DependentNameTypeLoc TL = + (*TSI)->getTypeLoc().castAs<DependentNameTypeLoc>(); + TL.setElaboratedKeywordLoc(KeywordLoc); + TL.setQualifierLoc(QualifierLoc); + TL.setNameLoc(IILoc); + } else { + ElaboratedTypeLoc TL = (*TSI)->getTypeLoc().castAs<ElaboratedTypeLoc>(); + TL.setElaboratedKeywordLoc(KeywordLoc); + TL.setQualifierLoc(QualifierLoc); + TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IILoc); + } + return T; +} + /// Build the type that describes a C++ typename specifier, /// e.g., "typename T::type". QualType @@ -10173,32 +10381,38 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, SourceLocation KeywordLoc, NestedNameSpecifierLoc QualifierLoc, const IdentifierInfo &II, - SourceLocation IILoc) { + SourceLocation IILoc, bool DeducedTSTContext) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); - DeclContext *Ctx = computeDeclContext(SS); - if (!Ctx) { - // If the nested-name-specifier is dependent and couldn't be - // resolved to a type, build a typename type. - assert(QualifierLoc.getNestedNameSpecifier()->isDependent()); - return Context.getDependentNameType(Keyword, - QualifierLoc.getNestedNameSpecifier(), - &II); + DeclContext *Ctx = nullptr; + if (QualifierLoc) { + Ctx = computeDeclContext(SS); + if (!Ctx) { + // If the nested-name-specifier is dependent and couldn't be + // resolved to a type, build a typename type. + assert(QualifierLoc.getNestedNameSpecifier()->isDependent()); + return Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + &II); + } + + // If the nested-name-specifier refers to the current instantiation, + // the "typename" keyword itself is superfluous. In C++03, the + // program is actually ill-formed. However, DR 382 (in C++0x CD1) + // allows such extraneous "typename" keywords, and we retroactively + // apply this DR to C++03 code with only a warning. In any case we continue. + + if (RequireCompleteDeclContext(SS, Ctx)) + return QualType(); } - // If the nested-name-specifier refers to the current instantiation, - // the "typename" keyword itself is superfluous. In C++03, the - // program is actually ill-formed. However, DR 382 (in C++0x CD1) - // allows such extraneous "typename" keywords, and we retroactively - // apply this DR to C++03 code with only a warning. In any case we continue. - - if (RequireCompleteDeclContext(SS, Ctx)) - return QualType(); - DeclarationName Name(&II); LookupResult Result(*this, Name, IILoc, LookupOrdinaryName); - LookupQualifiedName(Result, Ctx, SS); + if (Ctx) + LookupQualifiedName(Result, Ctx, SS); + else + LookupName(Result, CurScope); unsigned DiagID = 0; Decl *Referenced = nullptr; switch (Result.getResultKind()) { @@ -10207,7 +10421,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // a more specific diagnostic. SourceRange CondRange; Expr *Cond = nullptr; - if (isEnableIf(QualifierLoc, II, CondRange, Cond)) { + if (Ctx && isEnableIf(QualifierLoc, II, CondRange, Cond)) { // If we have a condition, narrow it down to the specific failed // condition. if (Cond) { @@ -10223,12 +10437,14 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, return QualType(); } - Diag(CondRange.getBegin(), diag::err_typename_nested_not_found_enable_if) + Diag(CondRange.getBegin(), + diag::err_typename_nested_not_found_enable_if) << Ctx << CondRange; return QualType(); } - DiagID = diag::err_typename_nested_not_found; + DiagID = Ctx ? diag::err_typename_nested_not_found + : diag::err_unknown_typename; break; } @@ -10294,6 +10510,19 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // is a placeholder for a deduced class type [...]. if (getLangOpts().CPlusPlus17) { if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) { + if (!DeducedTSTContext) { + QualType T(QualifierLoc + ? QualifierLoc.getNestedNameSpecifier()->getAsType() + : nullptr, 0); + if (!T.isNull()) + Diag(IILoc, diag::err_dependent_deduced_tst) + << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << T; + else + Diag(IILoc, diag::err_deduced_tst) + << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)); + Diag(TD->getLocation(), diag::note_template_decl_here); + return QualType(); + } return Context.getElaboratedType( Keyword, QualifierLoc.getNestedNameSpecifier(), Context.getDeducedTemplateSpecializationType(TemplateName(TD), @@ -10301,12 +10530,14 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, } } - DiagID = diag::err_typename_nested_not_type; + DiagID = Ctx ? diag::err_typename_nested_not_type + : diag::err_typename_not_type; Referenced = Result.getFoundDecl(); break; case LookupResult::FoundOverloaded: - DiagID = diag::err_typename_nested_not_type; + DiagID = Ctx ? diag::err_typename_nested_not_type + : diag::err_typename_not_type; Referenced = *Result.begin(); break; @@ -10318,9 +10549,14 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // type. Emit an appropriate diagnostic and return an error. SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(), IILoc); - Diag(IILoc, DiagID) << FullRange << Name << Ctx; + if (Ctx) + Diag(IILoc, DiagID) << FullRange << Name << Ctx; + else + Diag(IILoc, DiagID) << FullRange << Name; if (Referenced) - Diag(Referenced->getLocation(), diag::note_typename_refers_here) + Diag(Referenced->getLocation(), + Ctx ? diag::note_typename_member_refers_here + : diag::note_typename_refers_here) << Name; return QualType(); } @@ -10515,7 +10751,7 @@ Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, } Out << ']'; - return Out.str(); + return std::string(Out.str()); } void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD, |