diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 338 | 
1 files changed, 224 insertions, 114 deletions
| diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 1184446796eba..f961244da0726 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1050,7 +1050,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 +1081,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 +1150,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 +1172,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.  /// @@ -1319,6 +1365,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(); @@ -2762,7 +2813,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 +2921,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 +2944,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 +3037,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 +3079,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(          if (ExpectedTemplateParams &&              !TemplateParameterListsAreEqual(ParamLists[ParamIdx],                                              ExpectedTemplateParams, -                                            true, TPL_TemplateMatch)) +                                            !SuppressDiagnostic, TPL_TemplateMatch))            Invalid = true;          if (!Invalid && @@ -3037,9 +3091,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 +3130,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(); @@ -4044,7 +4101,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(      if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(),                                  Converted) && -        (!Context.getLangOpts().ConceptsTS || +        (!Context.getLangOpts().CPlusPlus2a ||           !TemplateParams->hasAssociatedConstraints())) {        // C++ [temp.class.spec]p9b3:        // @@ -6530,7 +6587,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() @@ -7102,6 +7164,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 +7939,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 +8113,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(      if (Context.hasSameType(CanonType,                          ClassTemplate->getInjectedClassNameSpecialization()) && -        (!Context.getLangOpts().ConceptsTS || +        (!Context.getLangOpts().CPlusPlus2a ||           !TemplateParams->hasAssociatedConstraints())) {        // C++ [temp.class.spec]p9b3:        // @@ -10012,24 +10077,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 +10219,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 +10255,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 +10295,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 +10311,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 +10384,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 +10404,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 +10423,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();  } | 
