llvm/clang/test/SemaTemplate/find-unexpanded-packs.cpp

// RUN: %clang_cc1 -verify %s -std=c++17 -Wno-unused

template<typename ...Ts> void PackInsideTypedefDeclaration() {
  ([] {
    typedef Ts Type;
    (void)Type();
  }(), ...);
}
template void PackInsideTypedefDeclaration<>();
template void PackInsideTypedefDeclaration<int>();
template void PackInsideTypedefDeclaration<int, float>();

template<typename ...Ts> void PackInsideTypedefDeclarationInvalid() {
  [] { // expected-error {{contains unexpanded parameter pack 'Ts'}}
    typedef Ts Type;
    (void)Type();
  };

  ([] {
    typedef Ts Type;
    // A reference to a typedef containing an unexpanded pack does not
    // itself contain an unexpanded pack.
    f(Type()...); // expected-error {{does not contain any unexpanded}}
  }, ...);
}


template<typename ...Ts> void PackInsideAliasDeclaration() {
  ([] {
    using Type = Ts;
    (void)Type();
  }(), ...);
}
template void PackInsideAliasDeclaration<>();
template void PackInsideAliasDeclaration<int>();
template void PackInsideAliasDeclaration<int, float>();

template<typename ...Ts> void PackInsideAliasDeclarationInvalid() {
  [] { // expected-error {{contains unexpanded parameter pack 'Ts'}}
    using Type = Ts;
    (void)Type();
  };
  ([] {
    using Type = Ts;
    // A reference to an alias containing an unexpanded pack does not
    // itself contain an unexpanded pack.
    f(Type()...); // expected-error {{does not contain any unexpanded}}
  }, ...);
}


template<typename ...Ts> void PackInsideUsingDeclaration() {
  ([] {
    struct A {
      using Type = Ts;
    };
    struct B : A {
      using typename A::Type;
    };
    (void)typename B::Type();
  }(), ...);
}
template void PackInsideUsingDeclaration<>();
template void PackInsideUsingDeclaration<int>();
template void PackInsideUsingDeclaration<int, float>();

template<typename ...Ts> void PackInsideUsingDeclarationInvalid() {
  ([] {
    struct A {
      using Type = Ts;
    };
    struct B : A {
      using typename A::Type...; // expected-error {{does not contain any unexpanded}}
    };
  }(), ...);
}


template<typename ...Ts> void PackInsideVarDeclaration() {
  ([] {
    Ts ts;
    (void)ts;
  }, ...);
}
template void PackInsideVarDeclaration<>();
template void PackInsideVarDeclaration<int>();
template void PackInsideVarDeclaration<int, float>();

template<typename ...Ts> void PackInsideVarDeclarationInvalid() {
  [] { // expected-error {{contains unexpanded parameter pack 'Ts'}}
    Ts ts;
    (void)ts;
  };
}


template<typename ...Ts> void PackInsideFunctionDeclaration() {
  ([] {
    Ts ts(Ts);
    ts({});
  }, ...);
}
template void PackInsideFunctionDeclaration<>();
template void PackInsideFunctionDeclaration<int>();
template void PackInsideFunctionDeclaration<int, float>();

template<typename ...Ts> void PackInsideFunctionDeclarationInvalid() {
  [] { // expected-error {{contains unexpanded parameter pack 'Ts'}}
    Ts ts(Ts);
    ts({});
  };
}


template<typename ...Ts> void PackInsideLocalClass() {
  ([] {
    class Local {
      Ts ts;
    };
    Local l;
  }, ...);
}
template void PackInsideLocalClass<>();
template void PackInsideLocalClass<int>();
template void PackInsideLocalClass<int, float>();

template<typename ...Ts> void PackInsideLocalClassInvalid() {
  [] { // expected-error {{contains unexpanded parameter pack 'Ts'}}
    class Local {
      Ts ts;
    };
    Local l;
  };
}

template<typename T> using Int = int;
struct AClass {};
template<typename T> using Class = AClass;
template<typename ...Ts> void HiddenPack() {
  (Int<Ts>(), ...);
  (Int<Ts>{}, ...);
  (Class<Ts>(), ...);
  (Class<Ts>{}, ...);

  ([] {
   Int<Ts>();
   }, ...);
  ([] {
   Int<Ts>{};
   }, ...);
  ([] {
   Class<Ts>();
   }, ...);
  ([] {
   Class<Ts>{};
   }, ...);
}
template void HiddenPack<>();
template void HiddenPack<int>();
template void HiddenPack<int, float>();

template<typename ...Ts> void HiddenPackInvalid() {
  Int<Ts>(); // expected-error {{unexpanded}}
  Int<Ts>{}; // expected-error {{unexpanded}}
  Class<Ts>(); // expected-error {{unexpanded}}
  Class<Ts>{}; // expected-error {{unexpanded}}
}