diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2020-01-17 20:45:01 +0000 | 
| commit | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch) | |
| tree | 4adf86a776049cbf7f69a1929c4babcbbef925eb /clang/lib/AST/DeclTemplate.cpp | |
| parent | 7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff) | |
Notes
Diffstat (limited to 'clang/lib/AST/DeclTemplate.cpp')
| -rw-r--r-- | clang/lib/AST/DeclTemplate.cpp | 212 | 
1 files changed, 169 insertions, 43 deletions
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 7e013c6c54d8f..95a2e26e0df84 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -43,35 +43,46 @@ using namespace clang;  // TemplateParameterList Implementation  //===----------------------------------------------------------------------===// -TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, + +TemplateParameterList::TemplateParameterList(const ASTContext& C, +                                             SourceLocation TemplateLoc,                                               SourceLocation LAngleLoc,                                               ArrayRef<NamedDecl *> Params,                                               SourceLocation RAngleLoc,                                               Expr *RequiresClause)      : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),        NumParams(Params.size()), ContainsUnexpandedParameterPack(false), -      HasRequiresClause(static_cast<bool>(RequiresClause)) { +      HasRequiresClause(RequiresClause != nullptr), +      HasConstrainedParameters(false) {    for (unsigned Idx = 0; Idx < NumParams; ++Idx) {      NamedDecl *P = Params[Idx];      begin()[Idx] = P; -    if (!P->isTemplateParameterPack()) { -      if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) -        if (NTTP->getType()->containsUnexpandedParameterPack()) -          ContainsUnexpandedParameterPack = true; - -      if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) -        if (TTP->getTemplateParameters()->containsUnexpandedParameterPack()) -          ContainsUnexpandedParameterPack = true; - -      // FIXME: If a default argument contains an unexpanded parameter pack, the -      // template parameter list does too. +    bool IsPack = P->isTemplateParameterPack(); +    if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) { +      if (!IsPack && NTTP->getType()->containsUnexpandedParameterPack()) +        ContainsUnexpandedParameterPack = true; +      if (NTTP->hasPlaceholderTypeConstraint()) +        HasConstrainedParameters = true; +    } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) { +      if (!IsPack && +          TTP->getTemplateParameters()->containsUnexpandedParameterPack()) +        ContainsUnexpandedParameterPack = true; +    } else if (const TypeConstraint *TC = +        cast<TemplateTypeParmDecl>(P)->getTypeConstraint()) { +      if (TC->getImmediatelyDeclaredConstraint() +          ->containsUnexpandedParameterPack()) +        ContainsUnexpandedParameterPack = true; +      HasConstrainedParameters = true;      } +    // FIXME: If a default argument contains an unexpanded parameter pack, the +    // template parameter list does too.    } -  if (RequiresClause) { -    *getTrailingObjects<Expr *>() = RequiresClause; + +  if (HasRequiresClause) {      if (RequiresClause->containsUnexpandedParameterPack())        ContainsUnexpandedParameterPack = true; +    *getTrailingObjects<Expr *>() = RequiresClause;    }  } @@ -83,7 +94,7 @@ TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,    void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *, Expr *>(                               Params.size(), RequiresClause ? 1u : 0u),                           alignof(TemplateParameterList)); -  return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params, +  return new (Mem) TemplateParameterList(C, TemplateLoc, LAngleLoc, Params,                                           RAngleLoc, RequiresClause);  } @@ -91,11 +102,23 @@ unsigned TemplateParameterList::getMinRequiredArguments() const {    unsigned NumRequiredArgs = 0;    for (const NamedDecl *P : asArray()) {      if (P->isTemplateParameterPack()) { -      if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) +      if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {          if (NTTP->isExpandedParameterPack()) {            NumRequiredArgs += NTTP->getNumExpansionTypes();            continue;          } +      } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) { +        if (TTP->isExpandedParameterPack()) { +          NumRequiredArgs += TTP->getNumExpansionParameters(); +          continue; +        } +      } else { +        const auto *TP = cast<TemplateTemplateParmDecl>(P); +        if (TP->isExpandedParameterPack()) { +          NumRequiredArgs += TP->getNumExpansionTemplateParameters(); +          continue; +        } +      }        break;      } @@ -140,14 +163,17 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params,  void TemplateParameterList::  getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { -  // TODO: Concepts: Collect immediately-introduced constraints. +  if (HasConstrainedParameters) +    for (const NamedDecl *Param : *this) +      if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) +        if (const auto *TC = TTP->getTypeConstraint()) +          AC.push_back(TC->getImmediatelyDeclaredConstraint());    if (HasRequiresClause)      AC.push_back(getRequiresClause());  }  bool TemplateParameterList::hasAssociatedConstraints() const { -  // TODO: Concepts: Regard immediately-introduced constraints. -  return HasRequiresClause; +  return HasRequiresClause || HasConstrainedParameters;  }  namespace clang { @@ -171,13 +197,18 @@ void TemplateDecl::anchor() {}  void TemplateDecl::  getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { -  // TODO: Concepts: Append function trailing requires clause.    TemplateParams->getAssociatedConstraints(AC); +  if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl())) +    if (const Expr *TRC = FD->getTrailingRequiresClause()) +      AC.push_back(TRC);  }  bool TemplateDecl::hasAssociatedConstraints() const { -  // TODO: Concepts: Regard function trailing requires clause. -  return TemplateParams->hasAssociatedConstraints(); +  if (TemplateParams->hasAssociatedConstraints()) +    return true; +  if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl())) +    return FD->getTrailingRequiresClause(); +  return false;  }  //===----------------------------------------------------------------------===// @@ -231,15 +262,16 @@ void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {    }  } -template<class EntryType> +template<class EntryType, typename... ProfileArguments>  typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *  RedeclarableTemplateDecl::findSpecializationImpl( -    llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args, -    void *&InsertPos) { +    llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos, +    ProfileArguments&&... ProfileArgs) {    using SETraits = SpecEntryTraits<EntryType>;    llvm::FoldingSetNodeID ID; -  EntryType::Profile(ID, Args, getASTContext()); +  EntryType::Profile(ID, std::forward<ProfileArguments>(ProfileArgs)..., +                     getASTContext());    EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);    return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;  } @@ -254,8 +286,8 @@ void RedeclarableTemplateDecl::addSpecializationImpl(  #ifndef NDEBUG      void *CorrectInsertPos;      assert(!findSpecializationImpl(Specializations, -                                   SETraits::getTemplateArgs(Entry), -                                   CorrectInsertPos) && +                                   CorrectInsertPos, +                                   SETraits::getTemplateArgs(Entry)) &&             InsertPos == CorrectInsertPos &&             "given incorrect InsertPos for specialization");  #endif @@ -312,7 +344,7 @@ FunctionTemplateDecl::getSpecializations() const {  FunctionDecl *  FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,                                           void *&InsertPos) { -  return findSpecializationImpl(getSpecializations(), Args, InsertPos); +  return findSpecializationImpl(getSpecializations(), InsertPos, Args);  }  void FunctionTemplateDecl::addSpecialization( @@ -418,7 +450,7 @@ ClassTemplateDecl::newCommon(ASTContext &C) const {  ClassTemplateSpecializationDecl *  ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,                                        void *&InsertPos) { -  return findSpecializationImpl(getSpecializations(), Args, InsertPos); +  return findSpecializationImpl(getSpecializations(), InsertPos, Args);  }  void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, @@ -427,9 +459,48 @@ void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,  }  ClassTemplatePartialSpecializationDecl * -ClassTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args, -                                             void *&InsertPos) { -  return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos); +ClassTemplateDecl::findPartialSpecialization( +    ArrayRef<TemplateArgument> Args, +    TemplateParameterList *TPL, void *&InsertPos) { +  return findSpecializationImpl(getPartialSpecializations(), InsertPos, Args, +                                TPL); +} + +static void ProfileTemplateParameterList(ASTContext &C, +    llvm::FoldingSetNodeID &ID, const TemplateParameterList *TPL) { +  const Expr *RC = TPL->getRequiresClause(); +  ID.AddBoolean(RC != nullptr); +  if (RC) +    RC->Profile(ID, C, /*Canonical=*/true); +  ID.AddInteger(TPL->size()); +  for (NamedDecl *D : *TPL) { +    if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { +      ID.AddInteger(0); +      ID.AddBoolean(NTTP->isParameterPack()); +      NTTP->getType().getCanonicalType().Profile(ID); +      continue; +    } +    if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D)) { +      ID.AddInteger(1); +      ID.AddBoolean(TTP->isParameterPack()); +      // TODO: Concepts: profile type-constraints. +      continue; +    } +    const auto *TTP = cast<TemplateTemplateParmDecl>(D); +    ID.AddInteger(2); +    ID.AddBoolean(TTP->isParameterPack()); +    ProfileTemplateParameterList(C, ID, TTP->getTemplateParameters()); +  } +} + +void +ClassTemplatePartialSpecializationDecl::Profile(llvm::FoldingSetNodeID &ID, +    ArrayRef<TemplateArgument> TemplateArgs, TemplateParameterList *TPL, +    ASTContext &Context) { +  ID.AddInteger(TemplateArgs.size()); +  for (const TemplateArgument &TemplateArg : TemplateArgs) +    TemplateArg.Profile(ID, Context); +  ProfileTemplateParameterList(Context, ID, TPL);  }  void ClassTemplateDecl::AddPartialSpecialization( @@ -513,9 +584,14 @@ TemplateTypeParmDecl *  TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC,                               SourceLocation KeyLoc, SourceLocation NameLoc,                               unsigned D, unsigned P, IdentifierInfo *Id, -                             bool Typename, bool ParameterPack) { +                             bool Typename, bool ParameterPack, +                             bool HasTypeConstraint, +                             Optional<unsigned> NumExpanded) {    auto *TTPDecl = -      new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename); +      new (C, DC, +           additionalSizeToAlloc<TypeConstraint>(HasTypeConstraint ? 1 : 0)) +      TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename, +                           HasTypeConstraint, NumExpanded);    QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl);    TTPDecl->setTypeForDecl(TTPType.getTypePtr());    return TTPDecl; @@ -524,7 +600,17 @@ TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC,  TemplateTypeParmDecl *  TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {    return new (C, ID) TemplateTypeParmDecl(nullptr, SourceLocation(), -                                          SourceLocation(), nullptr, false); +                                          SourceLocation(), nullptr, false, +                                          false, None); +} + +TemplateTypeParmDecl * +TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID, +                                         bool HasTypeConstraint) { +  return new (C, ID, +              additionalSizeToAlloc<TypeConstraint>(HasTypeConstraint ? 1 : 0)) +         TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), +                              nullptr, false, HasTypeConstraint, None);  }  SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { @@ -557,6 +643,20 @@ bool TemplateTypeParmDecl::isParameterPack() const {    return getTypeForDecl()->castAs<TemplateTypeParmType>()->isParameterPack();  } +void TemplateTypeParmDecl::setTypeConstraint(NestedNameSpecifierLoc NNS, +    DeclarationNameInfo NameInfo, NamedDecl *FoundDecl, ConceptDecl *CD, +    const ASTTemplateArgumentListInfo *ArgsAsWritten, +    Expr *ImmediatelyDeclaredConstraint) { +  assert(HasTypeConstraint && +         "HasTypeConstraint=true must be passed at construction in order to " +         "call setTypeConstraint"); +  assert(!TypeConstraintInitialized && +         "TypeConstraint was already initialized!"); +  new (getTrailingObjects<TypeConstraint>()) TypeConstraint(NNS, NameInfo, +      FoundDecl, CD, ArgsAsWritten, ImmediatelyDeclaredConstraint); +  TypeConstraintInitialized = true; +} +  //===----------------------------------------------------------------------===//  // NonTypeTemplateParmDecl Method Implementations  //===----------------------------------------------------------------------===// @@ -1035,7 +1135,7 @@ VarTemplateDecl::newCommon(ASTContext &C) const {  VarTemplateSpecializationDecl *  VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,                                      void *&InsertPos) { -  return findSpecializationImpl(getSpecializations(), Args, InsertPos); +  return findSpecializationImpl(getSpecializations(), InsertPos, Args);  }  void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D, @@ -1045,8 +1145,19 @@ void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,  VarTemplatePartialSpecializationDecl *  VarTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args, -                                           void *&InsertPos) { -  return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos); +     TemplateParameterList *TPL, void *&InsertPos) { +  return findSpecializationImpl(getPartialSpecializations(), InsertPos, Args, +                                TPL); +} + +void +VarTemplatePartialSpecializationDecl::Profile(llvm::FoldingSetNodeID &ID, +    ArrayRef<TemplateArgument> TemplateArgs, TemplateParameterList *TPL, +    ASTContext &Context) { +  ID.AddInteger(TemplateArgs.size()); +  for (const TemplateArgument &TemplateArg : TemplateArgs) +    TemplateArg.Profile(ID, Context); +  ProfileTemplateParameterList(Context, ID, TPL);  }  void VarTemplateDecl::AddPartialSpecialization( @@ -1200,7 +1311,8 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {    // typename T    auto *T = TemplateTypeParmDecl::Create(        C, DC, SourceLocation(), SourceLocation(), /*Depth=*/1, /*Position=*/0, -      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false); +      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false, +      /*HasTypeConstraint=*/false);    T->setImplicit(true);    // T ...Ints @@ -1225,7 +1337,8 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {    // typename T    auto *TemplateTypeParm = TemplateTypeParmDecl::Create(        C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, -      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false); +      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false, +      /*HasTypeConstraint=*/false);    TemplateTypeParm->setImplicit(true);    // T N @@ -1253,7 +1366,8 @@ createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) {    // typename ...T    auto *Ts = TemplateTypeParmDecl::Create(        C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, -      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true); +      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true, +      /*HasTypeConstraint=*/false);    Ts->setImplicit(true);    // template <std::size_t Index, typename ...T> @@ -1283,3 +1397,15 @@ BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,      : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name,                     createBuiltinTemplateParameterList(C, DC, BTK)),        BTK(BTK) {} + +void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const { +  if (NestedNameSpec) +    NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy); +  ConceptName.printName(OS, Policy); +  if (hasExplicitTemplateArgs()) { +    OS << "<"; +    for (auto &ArgLoc : ArgsAsWritten->arguments()) +      ArgLoc.getArgument().print(Policy, OS); +    OS << ">"; +  } +}
\ No newline at end of file  | 
