Repository: llvm/llvm-project
File: clang/include/clang/Sema/Template.h (C/C++)

Code before:
    }

    /// Determine whether there is a non-NULL template argument at the
    /// given depth and index.
    ///
    /// There must exist a template argument list at the given depth.
    bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
      assert(Depth < getNumLevels());

      if (Depth < NumRetainedOuterLevels)
        return false;

      if (Index >=
          TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size())
        return false;

      return !(*this)(Depth, Index).isNull();
    }

    bool isAnyArgInstantiationDependent() const {
      for (ArgumentListLevel ListLevel : TemplateArgumentLists)
        for (const TemplateArgument &TA : ListLevel.Args)
          // There might be null template arguments representing unused template
          // parameter mappings in an MLTAL during concept checking.
          if (!TA.isNull() && TA.isInstantiationDependent())
            return true;
      return false;
    }

    /// Clear out a specific template argument.
    void setArgument(unsigned Depth, unsigned Index,
                     TemplateArgument Arg) {
      assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
      assert(Index <
             TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
      const_cast<TemplateArgument &>(
          TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg;
    }

    /// Add a new outmost level to the multi-level template argument
    /// list.
    /// A 'Final' substitution means that these Args don't need to be
    /// resugared later.
    void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args,
                                   bool Final) {
      assert(!NumRetainedOuterLevels &&
             "substituted args outside retained args?");
      assert(getKind() == TemplateSubstitutionKind::Specialization);
      TemplateArgumentLists.push_back(
          {{AssociatedDecl ? AssociatedDecl->getCanonicalDecl() : nullptr,
            Final},

Review comment (bug):
This change doesn't make sense to me: instantiation dependence is a property of how a template argument is *written*, so we should never be asking whether a canonical template argument is instantiation-dependent.

For example, a template argument `sizeof(sizeof(T() + 1))` is instantiation-dependent because its behavior under instantiation depends on `T` (it might be invalid), but it is canonically the non-dependent template type argument `sizeof(size_t)`, which wouldn't be instantiation-dependent. It would be a bug to say that `X<sizeof(sizeof(T() + 1))>` does not have any instantiation-dependent arguments -- it obviously does.

Code after:
    }

    /// Determine whether there is a non-NULL template argument at the
    /// given depth and index.
    ///
    /// There must exist a template argument list at the given depth.
    bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
      assert(Depth < getNumLevels());

      if (Depth < NumRetainedOuterLevels)
        return false;

      if (Index >=
          TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size())
        return false;

      return !(*this)(Depth, Index).isNull();
    }

    bool isAnyArgInstantiationDependent(const ASTContext &C) const {
      for (ArgumentListLevel ListLevel : TemplateArgumentLists)
        for (const TemplateArgument &TA : ListLevel.Args)
          // There might be null template arguments representing unused template
          // parameter mappings in an MLTAL during concept checking.
          if (!TA.isNull() &&
              C.getCanonicalTemplateArgument(TA).isInstantiationDependent())
            return true;
      return false;
    }

    /// Clear out a specific template argument.
    void setArgument(unsigned Depth, unsigned Index,
                     TemplateArgument Arg) {
      assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
      assert(Index <
             TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
      const_cast<TemplateArgument &>(
          TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg;
    }

    /// Add a new outmost level to the multi-level template argument
    /// list.
    /// A 'Final' substitution means that these Args don't need to be
    /// resugared later.
    void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args,
                                   bool Final) {
      assert(!NumRetainedOuterLevels &&
             "substituted args outside retained args?");
      assert(getKind() == TemplateSubstitutionKind::Specialization);
      TemplateArgumentLists.push_back(
          {{AssociatedDecl ? AssociatedDecl->getCanonicalDecl() : nullptr,