diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 | 
| commit | 2298981669bf3bd63335a4be179bc0f96823a8f4 (patch) | |
| tree | 1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/Sema/SemaTemplate.cpp | |
| parent | 9a83721404652cea39e9f02ae3e3b5c964602a5c (diff) | |
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
| -rw-r--r-- | lib/Sema/SemaTemplate.cpp | 609 | 
1 files changed, 452 insertions, 157 deletions
| diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 3f9dc989103fa..3212281cc34d2 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1,9 +1,8 @@  //===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===//  // -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception  //===----------------------------------------------------------------------===//  //  //  This file implements semantic analysis for C++ templates. @@ -67,17 +66,20 @@ static Expr *clang::formAssociatedConstraints(TemplateParameterList *Params,  /// Determine whether the declaration found is acceptable as the name  /// of a template and, if so, return that template declaration. Otherwise, -/// returns NULL. -static NamedDecl *isAcceptableTemplateName(ASTContext &Context, -                                           NamedDecl *Orig, -                                           bool AllowFunctionTemplates) { -  NamedDecl *D = Orig->getUnderlyingDecl(); +/// returns null. +/// +/// Note that this may return an UnresolvedUsingValueDecl if AllowDependent +/// is true. In all other cases it will return a TemplateDecl (or null). +NamedDecl *Sema::getAsTemplateNameDecl(NamedDecl *D, +                                       bool AllowFunctionTemplates, +                                       bool AllowDependent) { +  D = D->getUnderlyingDecl();    if (isa<TemplateDecl>(D)) {      if (!AllowFunctionTemplates && isa<FunctionTemplateDecl>(D))        return nullptr; -    return Orig; +    return D;    }    if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { @@ -108,55 +110,35 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context,    // 'using Dependent::foo;' can resolve to a template name.    // 'using typename Dependent::foo;' cannot (not even if 'foo' is an    // injected-class-name). -  if (isa<UnresolvedUsingValueDecl>(D)) +  if (AllowDependent && isa<UnresolvedUsingValueDecl>(D))      return D;    return nullptr;  }  void Sema::FilterAcceptableTemplateNames(LookupResult &R, -                                         bool AllowFunctionTemplates) { -  // The set of class templates we've already seen. -  llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates; +                                         bool AllowFunctionTemplates, +                                         bool AllowDependent) {    LookupResult::Filter filter = R.makeFilter();    while (filter.hasNext()) {      NamedDecl *Orig = filter.next(); -    NamedDecl *Repl = isAcceptableTemplateName(Context, Orig, -                                               AllowFunctionTemplates); -    if (!Repl) +    if (!getAsTemplateNameDecl(Orig, AllowFunctionTemplates, AllowDependent))        filter.erase(); -    else if (Repl != Orig) { - -      // C++ [temp.local]p3: -      //   A lookup that finds an injected-class-name (10.2) can result in an -      //   ambiguity in certain cases (for example, if it is found in more than -      //   one base class). If all of the injected-class-names that are found -      //   refer to specializations of the same class template, and if the name -      //   is used as a template-name, the reference refers to the class -      //   template itself and not a specialization thereof, and is not -      //   ambiguous. -      if (ClassTemplateDecl *ClassTmpl = dyn_cast<ClassTemplateDecl>(Repl)) -        if (!ClassTemplates.insert(ClassTmpl).second) { -          filter.erase(); -          continue; -        } - -      // FIXME: we promote access to public here as a workaround to -      // the fact that LookupResult doesn't let us remember that we -      // found this template through a particular injected class name, -      // which means we end up doing nasty things to the invariants. -      // Pretending that access is public is *much* safer. -      filter.replace(Repl, AS_public); -    }    }    filter.done();  }  bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R, -                                         bool AllowFunctionTemplates) { -  for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) -    if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates)) +                                         bool AllowFunctionTemplates, +                                         bool AllowDependent, +                                         bool AllowNonTemplateFunctions) { +  for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) { +    if (getAsTemplateNameDecl(*I, AllowFunctionTemplates, AllowDependent)) +      return true; +    if (AllowNonTemplateFunctions && +        isa<FunctionDecl>((*I)->getUnderlyingDecl()))        return true; +  }    return false;  } @@ -194,25 +176,64 @@ TemplateNameKind Sema::isTemplateName(Scope *S,    QualType ObjectType = ObjectTypePtr.get(); +  AssumedTemplateKind AssumedTemplate;    LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName);    if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext, -                         MemberOfUnknownSpecialization)) +                         MemberOfUnknownSpecialization, SourceLocation(), +                         &AssumedTemplate))      return TNK_Non_template; -  if (R.empty()) return TNK_Non_template; -  if (R.isAmbiguous()) { -    // Suppress diagnostics;  we'll redo this lookup later. -    R.suppressDiagnostics(); -    // FIXME: we might have ambiguous templates, in which case we -    // should at least parse them properly! +  if (AssumedTemplate != AssumedTemplateKind::None) { +    TemplateResult = TemplateTy::make(Context.getAssumedTemplateName(TName)); +    // Let the parser know whether we found nothing or found functions; if we +    // found nothing, we want to more carefully check whether this is actually +    // a function template name versus some other kind of undeclared identifier. +    return AssumedTemplate == AssumedTemplateKind::FoundNothing +               ? TNK_Undeclared_template +               : TNK_Function_template; +  } + +  if (R.empty())      return TNK_Non_template; + +  NamedDecl *D = nullptr; +  if (R.isAmbiguous()) { +    // If we got an ambiguity involving a non-function template, treat this +    // as a template name, and pick an arbitrary template for error recovery. +    bool AnyFunctionTemplates = false; +    for (NamedDecl *FoundD : R) { +      if (NamedDecl *FoundTemplate = getAsTemplateNameDecl(FoundD)) { +        if (isa<FunctionTemplateDecl>(FoundTemplate)) +          AnyFunctionTemplates = true; +        else { +          D = FoundTemplate; +          break; +        } +      } +    } + +    // If we didn't find any templates at all, this isn't a template name. +    // Leave the ambiguity for a later lookup to diagnose. +    if (!D && !AnyFunctionTemplates) { +      R.suppressDiagnostics(); +      return TNK_Non_template; +    } + +    // If the only templates were function templates, filter out the rest. +    // We'll diagnose the ambiguity later. +    if (!D) +      FilterAcceptableTemplateNames(R);    } +  // At this point, we have either picked a single template name declaration D +  // or we have a non-empty set of results R containing either one template name +  // declaration or a set of function templates. +    TemplateName Template;    TemplateNameKind TemplateKind;    unsigned ResultCount = R.end() - R.begin(); -  if (ResultCount > 1) { +  if (!D && ResultCount > 1) {      // We assume that we'll preserve the qualifier from a function      // template name in other ways.      Template = Context.getOverloadedTemplateName(R.begin(), R.end()); @@ -220,12 +241,19 @@ TemplateNameKind Sema::isTemplateName(Scope *S,      // We'll do this lookup again later.      R.suppressDiagnostics(); -  } else if (isa<UnresolvedUsingValueDecl>((*R.begin())->getUnderlyingDecl())) { -    // We don't yet know whether this is a template-name or not. -    MemberOfUnknownSpecialization = true; -    return TNK_Non_template;    } else { -    TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl()); +    if (!D) { +      D = getAsTemplateNameDecl(*R.begin()); +      assert(D && "unambiguous result is not a template name"); +    } + +    if (isa<UnresolvedUsingValueDecl>(D)) { +      // We don't yet know whether this is a template-name or not. +      MemberOfUnknownSpecialization = true; +      return TNK_Non_template; +    } + +    TemplateDecl *TD = cast<TemplateDecl>(D);      if (SS.isSet() && !SS.isInvalid()) {        NestedNameSpecifier *Qualifier = SS.getScopeRep(); @@ -243,9 +271,11 @@ TemplateNameKind Sema::isTemplateName(Scope *S,      } else {        assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||               isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) || -             isa<BuiltinTemplateDecl>(TD)); +             isa<BuiltinTemplateDecl>(TD) || isa<ConceptDecl>(TD));        TemplateKind = -          isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template; +          isa<VarTemplateDecl>(TD) ? TNK_Var_template : +          isa<ConceptDecl>(TD) ? TNK_Concept_template : +          TNK_Type_template;      }    } @@ -316,7 +346,13 @@ bool Sema::LookupTemplateName(LookupResult &Found,                                QualType ObjectType,                                bool EnteringContext,                                bool &MemberOfUnknownSpecialization, -                              SourceLocation TemplateKWLoc) { +                              SourceLocation TemplateKWLoc, +                              AssumedTemplateKind *ATK) { +  if (ATK) +    *ATK = AssumedTemplateKind::None; + +  Found.setTemplateNameLookup(true); +    // Determine where to perform name lookup    MemberOfUnknownSpecialization = false;    DeclContext *LookupCtx = nullptr; @@ -391,24 +427,55 @@ bool Sema::LookupTemplateName(LookupResult &Found,      IsDependent |= Found.wasNotFoundInCurrentInstantiation();    } +  if (Found.isAmbiguous()) +    return false; + +  if (ATK && !SS.isSet() && ObjectType.isNull() && TemplateKWLoc.isInvalid()) { +    // 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 +    //   functions or finds nothing. +    // +    // To keep our behavior consistent, we apply the "finds nothing" part in +    // 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 && +        std::all_of(Found.begin(), Found.end(), [](NamedDecl *ND) { +          return isa<FunctionDecl>(ND->getUnderlyingDecl()); +        }); +    if (AllFunctions || (Found.empty() && !IsDependent)) { +      // If lookup found any functions, or if this is a name that can only be +      // used for a function, then strongly assume this is a function +      // template-id. +      *ATK = (Found.empty() && Found.getLookupName().isIdentifier()) +                 ? AssumedTemplateKind::FoundNothing +                 : AssumedTemplateKind::FoundFunctions; +      Found.clear(); +      return false; +    } +  } +    if (Found.empty() && !IsDependent) {      // If we did not find any names, attempt to correct any typos.      DeclarationName Name = Found.getLookupName();      Found.clear();      // Simple filter callback that, for keywords, only accepts the C++ *_cast -    auto FilterCCC = llvm::make_unique<CorrectionCandidateCallback>(); -    FilterCCC->WantTypeSpecifiers = false; -    FilterCCC->WantExpressionKeywords = false; -    FilterCCC->WantRemainingKeywords = false; -    FilterCCC->WantCXXNamedCasts = true; -    if (TypoCorrection Corrected = CorrectTypo( -            Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, -            std::move(FilterCCC), CTK_ErrorRecovery, LookupCtx)) { -      Found.setLookupName(Corrected.getCorrection()); +    DefaultFilterCCC FilterCCC{}; +    FilterCCC.WantTypeSpecifiers = false; +    FilterCCC.WantExpressionKeywords = false; +    FilterCCC.WantRemainingKeywords = false; +    FilterCCC.WantCXXNamedCasts = true; +    if (TypoCorrection Corrected = +            CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S, +                        &SS, FilterCCC, CTK_ErrorRecovery, LookupCtx)) {        if (auto *ND = Corrected.getFoundDecl())          Found.addDecl(ND);        FilterAcceptableTemplateNames(Found); -      if (!Found.empty()) { +      if (Found.isAmbiguous()) { +        Found.clear(); +      } else if (!Found.empty()) { +        Found.setLookupName(Corrected.getCorrection());          if (LookupCtx) {            std::string CorrectedStr(Corrected.getAsString(getLangOpts()));            bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && @@ -420,8 +487,6 @@ bool Sema::LookupTemplateName(LookupResult &Found,            diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest) << Name);          }        } -    } else { -      Found.setLookupName(Name);      }    } @@ -458,14 +523,19 @@ bool Sema::LookupTemplateName(LookupResult &Found,      // Note: C++11 does not perform this second lookup.      LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),                              LookupOrdinaryName); +    FoundOuter.setTemplateNameLookup(true);      LookupName(FoundOuter, S); +    // FIXME: We silently accept an ambiguous lookup here, in violation of +    // [basic.lookup]/1.      FilterAcceptableTemplateNames(FoundOuter, /*AllowFunctionTemplates=*/false); +    NamedDecl *OuterTemplate;      if (FoundOuter.empty()) {        //   - if the name is not found, the name found in the class of the        //     object expression is used, otherwise -    } else if (!FoundOuter.getAsSingle<ClassTemplateDecl>() || -               FoundOuter.isAmbiguous()) { +    } else if (FoundOuter.isAmbiguous() || !FoundOuter.isSingleResult() || +               !(OuterTemplate = +                     getAsTemplateNameDecl(FoundOuter.getFoundDecl()))) {        //   - if the name is found in the context of the entire        //     postfix-expression and does not name a class template, the name        //     found in the class of the object expression is used, otherwise @@ -475,8 +545,8 @@ bool Sema::LookupTemplateName(LookupResult &Found,        //     entity as the one found in the class of the object expression,        //     otherwise the program is ill-formed.        if (!Found.isSingleResult() || -          Found.getFoundDecl()->getCanonicalDecl() -            != FoundOuter.getFoundDecl()->getCanonicalDecl()) { +          getAsTemplateNameDecl(Found.getFoundDecl())->getCanonicalDecl() != +              OuterTemplate->getCanonicalDecl()) {          Diag(Found.getNameLoc(),               diag::ext_nested_name_member_ref_lookup_ambiguous)            << Found.getLookupName() @@ -546,7 +616,8 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,    // Try to correct the name by looking for templates and C++ named casts.    struct TemplateCandidateFilter : CorrectionCandidateCallback { -    TemplateCandidateFilter() { +    Sema &S; +    TemplateCandidateFilter(Sema &S) : S(S) {        WantTypeSpecifiers = false;        WantExpressionKeywords = false;        WantRemainingKeywords = false; @@ -554,20 +625,22 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,      };      bool ValidateCandidate(const TypoCorrection &Candidate) override {        if (auto *ND = Candidate.getCorrectionDecl()) -        return isAcceptableTemplateName(ND->getASTContext(), ND, true); +        return S.getAsTemplateNameDecl(ND);        return Candidate.isKeyword();      } + +    std::unique_ptr<CorrectionCandidateCallback> clone() override { +      return llvm::make_unique<TemplateCandidateFilter>(*this); +    }    };    DeclarationName Name = NameInfo.getName(); -  if (TypoCorrection Corrected = -          CorrectTypo(NameInfo, LookupKind, S, &SS, -                      llvm::make_unique<TemplateCandidateFilter>(), -                      CTK_ErrorRecovery, LookupCtx)) { +  TemplateCandidateFilter CCC(*this); +  if (TypoCorrection Corrected = CorrectTypo(NameInfo, LookupKind, S, &SS, CCC, +                                             CTK_ErrorRecovery, LookupCtx)) {      auto *ND = Corrected.getFoundDecl();      if (ND) -      ND = isAcceptableTemplateName(Context, ND, -                                    /*AllowFunctionTemplates*/ true); +      ND = getAsTemplateNameDecl(ND);      if (ND || Corrected.isKeyword()) {        if (LookupCtx) {          std::string CorrectedStr(Corrected.getAsString(getLangOpts())); @@ -1076,7 +1149,7 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,      //   variable or variable template or the declaration of a function or      //   function template. -    if (DS.isConstexprSpecified()) +    if (DS.hasConstexprSpecifier())        EmitDiag(DS.getConstexprSpecLoc());      // [dcl.fct.spec]p1: @@ -1085,7 +1158,7 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,      if (DS.isVirtualSpecified())        EmitDiag(DS.getVirtualSpecLoc()); -    if (DS.isExplicitSpecified()) +    if (DS.hasExplicitSpecifier())        EmitDiag(DS.getExplicitSpecLoc());      if (DS.isNoreturnSpecified()) @@ -1110,6 +1183,8 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,      Invalid = true;    } +  CheckFunctionOrTemplateParamDeclarator(S, D); +    IdentifierInfo *ParamName = D.getIdentifier();    bool IsParameterPack = D.hasEllipsis();    NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create( @@ -1765,8 +1840,8 @@ struct ConvertConstructorToDeductionGuideTransform {        return nullptr;      TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType); -    return buildDeductionGuide(TemplateParams, CD->isExplicit(), NewTInfo, -                               CD->getBeginLoc(), CD->getLocation(), +    return buildDeductionGuide(TemplateParams, CD->getExplicitSpecifier(), +                               NewTInfo, CD->getBeginLoc(), CD->getLocation(),                                 CD->getEndLoc());    } @@ -1795,8 +1870,8 @@ struct ConvertConstructorToDeductionGuideTransform {        Params.push_back(NewParam);      } -    return buildDeductionGuide(Template->getTemplateParameters(), false, TSI, -                               Loc, Loc, Loc); +    return buildDeductionGuide(Template->getTemplateParameters(), +                               ExplicitSpecifier(), TSI, Loc, Loc, Loc);    }  private: @@ -1946,7 +2021,7 @@ private:    }    NamedDecl *buildDeductionGuide(TemplateParameterList *TemplateParams, -                                 bool Explicit, TypeSourceInfo *TInfo, +                                 ExplicitSpecifier ES, TypeSourceInfo *TInfo,                                   SourceLocation LocStart, SourceLocation Loc,                                   SourceLocation LocEnd) {      DeclarationNameInfo Name(DeductionGuideName, Loc); @@ -1955,8 +2030,8 @@ private:      // Build the implicit deduction guide template.      auto *Guide = -        CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, Explicit, -                                      Name, TInfo->getType(), TInfo, LocEnd); +        CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name, +                                      TInfo->getType(), TInfo, LocEnd);      Guide->setImplicit();      Guide->setParams(Params); @@ -1981,6 +2056,12 @@ private:  void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,                                            SourceLocation Loc) { +  if (CXXRecordDecl *DefRecord = +          cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) { +    TemplateDecl *DescribedTemplate = DefRecord->getDescribedClassTemplate(); +    Template = DescribedTemplate ? DescribedTemplate : Template; +  } +    DeclContext *DC = Template->getDeclContext();    if (DC->isDependentContext())      return; @@ -3148,7 +3229,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,    TemplateDecl *Template = Name.getAsTemplateDecl();    if (!Template || isa<FunctionTemplateDecl>(Template) || -      isa<VarTemplateDecl>(Template)) { +      isa<VarTemplateDecl>(Template) || +      isa<ConceptDecl>(Template)) {      // We might have a substituted template template parameter pack. If so,      // build a template specialization type for it.      if (Name.getAsSubstTemplateTemplateParmPack()) @@ -3324,14 +3406,65 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,    return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);  } -TypeResult -Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, -                          TemplateTy TemplateD, IdentifierInfo *TemplateII, -                          SourceLocation TemplateIILoc, -                          SourceLocation LAngleLoc, -                          ASTTemplateArgsPtr TemplateArgsIn, -                          SourceLocation RAngleLoc, -                          bool IsCtorOrDtorName, bool IsClassName) { +void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName, +                                           TemplateNameKind &TNK, +                                           SourceLocation NameLoc, +                                           IdentifierInfo *&II) { +  assert(TNK == TNK_Undeclared_template && "not an undeclared template name"); + +  TemplateName Name = ParsedName.get(); +  auto *ATN = Name.getAsAssumedTemplateName(); +  assert(ATN && "not an assumed template name"); +  II = ATN->getDeclName().getAsIdentifierInfo(); + +  if (!resolveAssumedTemplateNameAsType(S, Name, NameLoc, /*Diagnose*/false)) { +    // Resolved to a type template name. +    ParsedName = TemplateTy::make(Name); +    TNK = TNK_Type_template; +  } +} + +bool Sema::resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name, +                                            SourceLocation NameLoc, +                                            bool Diagnose) { +  // We assumed this undeclared identifier to be an (ADL-only) function +  // template name, but it was used in a context where a type was required. +  // Try to typo-correct it now. +  AssumedTemplateStorage *ATN = Name.getAsAssumedTemplateName(); +  assert(ATN && "not an assumed template name"); + +  LookupResult R(*this, ATN->getDeclName(), NameLoc, LookupOrdinaryName); +  struct CandidateCallback : CorrectionCandidateCallback { +    bool ValidateCandidate(const TypoCorrection &TC) override { +      return TC.getCorrectionDecl() && +             getAsTypeTemplateDecl(TC.getCorrectionDecl()); +    } +    std::unique_ptr<CorrectionCandidateCallback> clone() override { +      return llvm::make_unique<CandidateCallback>(*this); +    } +  } FilterCCC; + +  TypoCorrection Corrected = +      CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr, +                  FilterCCC, CTK_ErrorRecovery); +  if (Corrected && Corrected.getFoundDecl()) { +    diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest) +                                << ATN->getDeclName()); +    Name = TemplateName(Corrected.getCorrectionDeclAs<TemplateDecl>()); +    return false; +  } + +  if (Diagnose) +    Diag(R.getNameLoc(), diag::err_no_template) << R.getLookupName(); +  return true; +} + +TypeResult Sema::ActOnTemplateIdType( +    Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, +    TemplateTy TemplateD, IdentifierInfo *TemplateII, +    SourceLocation TemplateIILoc, SourceLocation LAngleLoc, +    ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc, +    bool IsCtorOrDtorName, bool IsClassName) {    if (SS.isInvalid())      return true; @@ -3372,6 +3505,9 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,    }    TemplateName Template = TemplateD.get(); +  if (Template.getAsAssumedTemplateName() && +      resolveAssumedTemplateNameAsType(S, Template, TemplateIILoc)) +    return true;    // Translate the parser's template argument list in our AST format.    TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); @@ -3903,13 +4039,6 @@ DeclResult Sema::ActOnVarTemplateSpecialization(      Specialization->setAccess(VarTemplate->getAccess());    } -  // Link instantiations of static data members back to the template from -  // which they were instantiated. -  if (Specialization->isStaticDataMember()) -    Specialization->setInstantiationOfStaticDataMember( -        VarTemplate->getTemplatedDecl(), -        Specialization->getSpecializationKind()); -    return Specialization;  } @@ -4108,6 +4237,18 @@ void Sema::diagnoseMissingTemplateArguments(TemplateName Name,    }  } +ExprResult +Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, +                             const DeclarationNameInfo &NameInfo, +                             ConceptDecl *Template, +                             SourceLocation TemplateLoc, +                             const TemplateArgumentListInfo *TemplateArgs) { +  // TODO: Do concept specialization here. +  Diag(NameInfo.getBeginLoc(), diag::err_concept_not_implemented) << +    "concept specialization"; +  return ExprError(); +} +  ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,                                       SourceLocation TemplateKWLoc,                                       LookupResult &R, @@ -4124,7 +4265,6 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,    //       vs template<class T, class U> void f(U);    // These should be filtered out by our callers. -  assert(!R.empty() && "empty lookup results when building templateid");    assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");    // Non-function templates require a template argument list. @@ -4149,6 +4289,12 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,                                TemplateKWLoc, TemplateArgs);    } +  if (R.getAsSingle<ConceptDecl>() && !AnyDependentArguments()) { +    return CheckConceptTemplateId(SS, R.getLookupNameInfo(), +                                  R.getAsSingle<ConceptDecl>(), +                                  TemplateKWLoc, TemplateArgs); +  } +    // We don't want lookup warnings at this point.    R.suppressDiagnostics(); @@ -4263,7 +4409,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,                       LookupOrdinaryName);        bool MOUS;        if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, -                              MOUS, TemplateKWLoc)) +                              MOUS, TemplateKWLoc) && !R.isAmbiguous())          Diag(Name.getBeginLoc(), diag::err_no_member)              << DNI.getName() << LookupCtx << SS.getRange();        return TNK_Non_template; @@ -4763,10 +4909,22 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,        TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,                                          Converted); -      NTTPType = SubstType(NTTPType, -                           MultiLevelTemplateArgumentList(TemplateArgs), -                           NTTP->getLocation(), -                           NTTP->getDeclName()); + +      // If the parameter is a pack expansion, expand this slice of the pack. +      if (auto *PET = NTTPType->getAs<PackExpansionType>()) { +        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, +                                                           ArgumentPackIndex); +        NTTPType = SubstType(PET->getPattern(), +                             MultiLevelTemplateArgumentList(TemplateArgs), +                             NTTP->getLocation(), +                             NTTP->getDeclName()); +      } else { +        NTTPType = SubstType(NTTPType, +                             MultiLevelTemplateArgumentList(TemplateArgs), +                             NTTP->getLocation(), +                             NTTP->getDeclName()); +      } +        // If that worked, check the non-type template parameter type        // for validity.        if (!NTTPType.isNull()) @@ -6185,12 +6343,13 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,      // When checking a deduced template argument, deduce from its type even if      // the type is dependent, in order to check the types of non-type template      // arguments line up properly in partial ordering. -    Optional<unsigned> Depth; -    if (CTAK != CTAK_Specified) -      Depth = Param->getDepth() + 1; +    Optional<unsigned> Depth = Param->getDepth() + 1; +    Expr *DeductionArg = Arg; +    if (auto *PE = dyn_cast<PackExpansionExpr>(DeductionArg)) +      DeductionArg = PE->getPattern();      if (DeduceAutoType(              Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()), -            Arg, ParamType, Depth) == DAR_Failed) { +            DeductionArg, ParamType, Depth) == DAR_Failed) {        Diag(Arg->getExprLoc(),             diag::err_non_type_template_parm_type_deduction_failure)          << Param->getDeclName() << Param->getType() << Arg->getType() @@ -6242,9 +6401,24 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,    // 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()) { -    // FIXME: Produce a cloned, canonical expression? -    Converted = TemplateArgument(Arg); -    return Arg; +    // Force the argument to the type of the parameter to maintain invariants. +    auto *PE = dyn_cast<PackExpansionExpr>(Arg); +    if (PE) +      Arg = PE->getPattern(); +    ExprResult E = ImpCastExprToType( +        Arg, ParamType.getNonLValueExprType(Context), CK_Dependent, +        ParamType->isLValueReferenceType() ? VK_LValue : +        ParamType->isRValueReferenceType() ? VK_XValue : VK_RValue); +    if (E.isInvalid()) +      return ExprError(); +    if (PE) { +      // Recreate a pack expansion if we unwrapped one. +      E = new (Context) +          PackExpansionExpr(E.get()->getType(), E.get(), PE->getEllipsisLoc(), +                            PE->getNumExpansions()); +    } +    Converted = TemplateArgument(E.get()); +    return E;    }    // The initialization of the parameter from the argument is @@ -6273,10 +6447,13 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,      // Convert the APValue to a TemplateArgument.      switch (Value.getKind()) { -    case APValue::Uninitialized: +    case APValue::None:        assert(ParamType->isNullPtrType());        Converted = TemplateArgument(CanonParamType, /*isNullPtr*/true);        break; +    case APValue::Indeterminate: +      llvm_unreachable("result of constant evaluation should be initialized"); +      break;      case APValue::Int:        assert(ParamType->isIntegralOrEnumerationType());        Converted = TemplateArgument(Context, Value.getInt(), CanonParamType); @@ -6307,21 +6484,22 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,        // -- a string literal        // -- the result of a typeid expression, or        // -- a predefined __func__ variable -      if (auto *E = Value.getLValueBase().dyn_cast<const Expr*>()) { -        if (isa<CXXUuidofExpr>(E)) { -          Converted = TemplateArgument(ArgResult.get()); +      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;          }          Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)              << Arg->getSourceRange();          return ExprError();        } -      auto *VD = const_cast<ValueDecl *>( -          Value.getLValueBase().dyn_cast<const ValueDecl *>());        // -- a subobject        if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 &&            VD && VD->getType()->isArrayType() && -          Value.getLValuePath()[0].ArrayIndex == 0 && +          Value.getLValuePath()[0].getAsArrayIndex() == 0 &&            !Value.isLValueOnePastTheEnd() && ParamType->isPointerType()) {          // Per defect report (no number yet):          //   ... other than a pointer to the first element of a complete array @@ -6342,6 +6520,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,      }      case APValue::AddrLabelDiff:        return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff); +    case APValue::FixedPoint:      case APValue::Float:      case APValue::ComplexInt:      case APValue::ComplexFloat: @@ -7816,7 +7995,74 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,    return NewDecl;  } -/// Strips various properties off an implicit instantiation +Decl *Sema::ActOnConceptDefinition(Scope *S, +                              MultiTemplateParamsArg TemplateParameterLists, +                                   IdentifierInfo *Name, SourceLocation NameLoc, +                                   Expr *ConstraintExpr) { +  DeclContext *DC = CurContext; + +  if (!DC->getRedeclContext()->isFileContext()) { +    Diag(NameLoc, +      diag::err_concept_decls_may_only_appear_in_global_namespace_scope); +    return nullptr; +  } + +  if (TemplateParameterLists.size() > 1) { +    Diag(NameLoc, diag::err_concept_extra_headers); +    return nullptr; +  } + +  if (TemplateParameterLists.front()->size() == 0) { +    Diag(NameLoc, diag::err_concept_no_parameters); +    return nullptr; +  } + +  ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name, +                                             TemplateParameterLists.front(), +                                             ConstraintExpr); + +  if (!ConstraintExpr->isTypeDependent() && +      ConstraintExpr->getType() != Context.BoolTy) { +    // C++2a [temp.constr.atomic]p3: +    // E shall be a constant expression of type bool. +    // TODO: Do this check for individual atomic constraints +    // and not the constraint expression. Probably should do it in +    // ParseConstraintExpression. +    Diag(ConstraintExpr->getSourceRange().getBegin(), +        diag::err_concept_initialized_with_non_bool_type) +      << ConstraintExpr->getType(); +    NewDecl->setInvalidDecl(); +  } + +  if (NewDecl->getAssociatedConstraints()) { +    // C++2a [temp.concept]p4: +    // A concept shall not have associated constraints. +    // TODO: Make a test once we have actual associated constraints. +    Diag(NameLoc, diag::err_concept_no_associated_constraints); +    NewDecl->setInvalidDecl(); +  } + +  // Check for conflicting previous declaration. +  DeclarationNameInfo NameInfo(NewDecl->getDeclName(), NameLoc); +  LookupResult Previous(*this, NameInfo, LookupOrdinaryName, +                        ForVisibleRedeclaration); +  LookupName(Previous, S); + +  FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage=*/false, +                       /*AllowInlineNamespace*/false); +  if (!Previous.empty()) { +    auto *Old = Previous.getRepresentativeDecl(); +    Diag(NameLoc, isa<ConceptDecl>(Old) ? diag::err_redefinition : +         diag::err_redefinition_different_kind) << NewDecl->getDeclName(); +    Diag(Old->getLocation(), diag::note_previous_definition); +  } + +  ActOnDocumentableDecl(NewDecl); +  PushOnScopeChains(NewDecl, S); +  return NewDecl; +} + +/// \brief Strips various properties off an implicit instantiation  /// that has just been explicitly specialized.  static void StripImplicitInstantiation(NamedDecl *D) {    D->dropAttr<DLLImportAttr>(); @@ -8182,8 +8428,8 @@ bool Sema::CheckFunctionTemplateSpecialization(        // here that have a different target.        if (LangOpts.CUDA &&            IdentifyCUDATarget(Specialization, -                             /* IgnoreImplicitHDAttributes = */ true) != -              IdentifyCUDATarget(FD, /* IgnoreImplicitHDAttributes = */ true)) { +                             /* IgnoreImplicitHDAttr = */ true) != +              IdentifyCUDATarget(FD, /* IgnoreImplicitHDAttr = */ true)) {          FailedCandidates.addCandidate().set(              I.getPair(), FunTmpl->getTemplatedDecl(),              MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info)); @@ -8243,7 +8489,7 @@ bool Sema::CheckFunctionTemplateSpecialization(      // FIXME: We need an update record for this AST mutation.      // FIXME: What if there are multiple such prior declarations (for instance,      // from different modules)? -    Specialization->setConstexpr(FD->isConstexpr()); +    Specialization->setConstexprKind(FD->getConstexprKind());    }    // FIXME: Check if the prior specialization has a point of instantiation. @@ -8594,6 +8840,29 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,    return false;  } +/// Common checks for whether an explicit instantiation of \p D is valid. +static bool CheckExplicitInstantiation(Sema &S, NamedDecl *D, +                                       SourceLocation InstLoc, +                                       bool WasQualifiedName, +                                       TemplateSpecializationKind TSK) { +  // C++ [temp.explicit]p13: +  //   An explicit instantiation declaration shall not name a specialization of +  //   a template with internal linkage. +  if (TSK == TSK_ExplicitInstantiationDeclaration && +      D->getFormalLinkage() == InternalLinkage) { +    S.Diag(InstLoc, diag::err_explicit_instantiation_internal_linkage) << D; +    return true; +  } + +  // C++11 [temp.explicit]p3: [DR 275] +  //   An explicit instantiation shall appear in an enclosing namespace of its +  //   template. +  if (CheckExplicitInstantiationScope(S, D, InstLoc, WasQualifiedName)) +    return true; + +  return false; +} +  /// Determine whether the given scope specifier has a template-id in it.  static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {    if (!SS.isSet()) @@ -8684,8 +8953,10 @@ DeclResult Sema::ActOnExplicitInstantiation(                                         ? TSK_ExplicitInstantiationDefinition                                         : TSK_ExplicitInstantiationDeclaration; -  if (TSK == TSK_ExplicitInstantiationDeclaration) { -    // Check for dllexport class template instantiation declarations. +  if (TSK == TSK_ExplicitInstantiationDeclaration && +      !Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) { +    // Check for dllexport class template instantiation declarations, +    // except for MinGW mode.      for (const ParsedAttr &AL : Attr) {        if (AL.getKind() == ParsedAttr::AT_DLLExport) {          Diag(ExternLoc, @@ -8745,13 +9016,21 @@ DeclResult Sema::ActOnExplicitInstantiation(    TemplateSpecializationKind PrevDecl_TSK      = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared; -  // C++0x [temp.explicit]p2: -  //   [...] An explicit instantiation shall appear in an enclosing -  //   namespace of its template. [...] -  // -  // This is C++ DR 275. -  if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc, -                                      SS.isSet())) +  if (TSK == TSK_ExplicitInstantiationDefinition && PrevDecl != nullptr && +      Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) { +    // Check for dllexport class template instantiation definitions in MinGW +    // mode, if a previous declaration of the instantiation was seen. +    for (const ParsedAttr &AL : Attr) { +      if (AL.getKind() == ParsedAttr::AT_DLLExport) { +        Diag(AL.getLoc(), +             diag::warn_attribute_dllexport_explicit_instantiation_def); +        break; +      } +    } +  } + +  if (CheckExplicitInstantiation(*this, ClassTemplate, TemplateNameLoc, +                                 SS.isSet(), TSK))      return true;    ClassTemplateSpecializationDecl *Specialization = nullptr; @@ -8906,6 +9185,14 @@ DeclResult Sema::ActOnExplicitInstantiation(        dllExportImportClassTemplateSpecialization(*this, Def);      } +    // In MinGW mode, export the template instantiation if the declaration +    // was marked dllexport. +    if (PrevDecl_TSK == TSK_ExplicitInstantiationDeclaration && +        Context.getTargetInfo().getTriple().isWindowsGNUEnvironment() && +        PrevDecl->hasAttr<DLLExportAttr>()) { +      dllExportImportClassTemplateSpecialization(*this, Def); +    } +      // Set the template specialization kind. Make sure it is set before      // instantiating the members which will trigger ASTConsumer callbacks.      Specialization->setTemplateSpecializationKind(TSK); @@ -8974,12 +9261,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,      = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition                             : TSK_ExplicitInstantiationDeclaration; -  // C++0x [temp.explicit]p2: -  //   [...] An explicit instantiation shall appear in an enclosing -  //   namespace of its template. [...] -  // -  // This is C++ DR 275. -  CheckExplicitInstantiationScope(*this, Record, NameLoc, true); +  CheckExplicitInstantiation(*this, Record, NameLoc, true, TSK);    // Verify that it is okay to explicitly instantiate here.    CXXRecordDecl *PrevDecl @@ -9096,7 +9378,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,             diag::err_explicit_instantiation_inline :             diag::warn_explicit_instantiation_inline_0x)        << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); -  if (D.getDeclSpec().isConstexprSpecified() && R->isFunctionType()) +  if (D.getDeclSpec().hasConstexprSpecifier() && R->isFunctionType())      // FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is      // not already specified.      Diag(D.getDeclSpec().getConstexprSpecLoc(), @@ -9137,7 +9419,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,      if (!PrevTemplate) {        if (!Prev || !Prev->isStaticDataMember()) { -        // We expect to see a data data member here. +        // We expect to see a static data member here.          Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known)              << Name;          for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); @@ -9210,8 +9492,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,             diag::ext_explicit_instantiation_without_qualified_id)          << Prev << D.getCXXScopeSpec().getRange(); -    // Check the scope of this explicit instantiation. -    CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true); +    CheckExplicitInstantiation(*this, Prev, D.getIdentifierLoc(), true, TSK);      // Verify that it is okay to explicitly instantiate here.      TemplateSpecializationKind PrevTSK = Prev->getTemplateSpecializationKind(); @@ -9306,7 +9587,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,      // have a different target.      if (LangOpts.CUDA &&          IdentifyCUDATarget(Specialization, -                           /* IgnoreImplicitHDAttributes = */ true) != +                           /* IgnoreImplicitHDAttr = */ true) !=              IdentifyCUDATarget(D.getDeclSpec().getAttributes())) {        FailedCandidates.addCandidate().set(            P.getPair(), FunTmpl->getTemplatedDecl(), @@ -9386,6 +9667,20 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,        return (Decl*) nullptr;    } +  // HACK: libc++ has a bug where it attempts to explicitly instantiate the +  // functions +  //     valarray<size_t>::valarray(size_t) and +  //     valarray<size_t>::~valarray() +  // that it declared to have internal linkage with the internal_linkage +  // attribute. Ignore the explicit instantiation declaration in this case. +  if (Specialization->hasAttr<InternalLinkageAttr>() && +      TSK == TSK_ExplicitInstantiationDeclaration) { +    if (auto *RD = dyn_cast<CXXRecordDecl>(Specialization->getDeclContext())) +      if (RD->getIdentifier() && RD->getIdentifier()->isStr("valarray") && +          RD->isInStdNamespace()) +        return (Decl*) nullptr; +  } +    ProcessDeclAttributeList(S, Specialization, D.getDeclSpec().getAttributes());    // In MSVC mode, dllimported explicit instantiation definitions are treated as @@ -9419,11 +9714,11 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,           diag::ext_explicit_instantiation_without_qualified_id)      << Specialization << D.getCXXScopeSpec().getRange(); -  CheckExplicitInstantiationScope(*this, -                   FunTmpl? (NamedDecl *)FunTmpl -                          : Specialization->getInstantiatedFromMemberFunction(), -                                  D.getIdentifierLoc(), -                                  D.getCXXScopeSpec().isSet()); +  CheckExplicitInstantiation( +      *this, +      FunTmpl ? (NamedDecl *)FunTmpl +              : Specialization->getInstantiatedFromMemberFunction(), +      D.getIdentifierLoc(), D.getCXXScopeSpec().isSet(), TSK);    // FIXME: Create some kind of ExplicitInstantiationDecl here.    return (Decl*) nullptr; | 
