=========================================
Namespace definitions
=========================================

namespace std {

int x;

}  // namespace std

namespace A::B { }
namespace A::B::inline C::D { }

---

(translation_unit
  (namespace_definition
    name: (identifier)
    body: (declaration_list
      (declaration
        type: (primitive_type)
        declarator: (identifier))))
  (comment)
  (namespace_definition
    name: (namespace_definition_name (identifier) (identifier))
    body: (declaration_list))
  (namespace_definition
    name: (namespace_definition_name
      (namespace_definition_name
        (namespace_definition_name (identifier) (identifier))
        (identifier))
      (identifier))
    body: (declaration_list)))

=========================================
Namespace alias definitions
=========================================

namespace A = B;
namespace C = ::D;
namespace fs = std::filesystem;
namespace bfs = ::boost::filesystem;
namespace literals = std::chono::literals;

---

(translation_unit
  (namespace_alias_definition
    name: (identifier)
    (identifier))
  (namespace_alias_definition
    name: (identifier)
    (qualified_identifier
      name: (identifier)))
  (namespace_alias_definition
    name: (identifier)
    (qualified_identifier
      scope: (namespace_identifier)
      name: (identifier)))
  (namespace_alias_definition
    name: (identifier)
    (qualified_identifier
      name: (qualified_identifier
        scope: (namespace_identifier)
        name: (identifier))))
  (namespace_alias_definition
    name: (identifier)
    (qualified_identifier
      scope: (namespace_identifier)
      name: (qualified_identifier
        scope: (namespace_identifier)
        name: (identifier)))))

=========================================
Using declarations
=========================================

using a;
using ::b;
using c::d;
using ::e::f::g;
using h = i::j;
using namespace std;

template <typename T>
using a = typename b<T>::c;

---

(translation_unit
  (using_declaration (identifier))
  (using_declaration (qualified_identifier (identifier)))
  (using_declaration (qualified_identifier (namespace_identifier) (identifier)))
  (using_declaration
    (qualified_identifier
      (qualified_identifier
        (namespace_identifier)
        (qualified_identifier
            (namespace_identifier)
            (identifier)))))
  (alias_declaration
    (type_identifier)
    (type_descriptor (qualified_identifier (namespace_identifier) (type_identifier))))
  (using_declaration (identifier))
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration (type_identifier)))
    (alias_declaration
      (type_identifier)
      (type_descriptor
        (dependent_type
          (qualified_identifier
            (template_type (type_identifier) (template_argument_list (type_descriptor (type_identifier))))
            (type_identifier)))))))

=========================================
Reference declarations
=========================================

int main() {
  T &x = y<T &>();
}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator (identifier) (parameter_list))
    (compound_statement
      (declaration
        (type_identifier)
        (init_declarator
          (reference_declarator (identifier))
          (call_expression
            (template_function
              (identifier)
              (template_argument_list
                (type_descriptor (type_identifier) (abstract_reference_declarator))))
            (argument_list)))))))

=========================================
R-value reference declarations
=========================================

int main(T &&);

int main(T &&t) {
  const U &&u = v;
}

---

(translation_unit
  (declaration
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list (parameter_declaration (type_identifier) (abstract_reference_declarator)))))
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list (parameter_declaration (type_identifier) (reference_declarator (identifier)))))
    (compound_statement
      (declaration
        (type_qualifier)
        (type_identifier)
        (init_declarator (reference_declarator (identifier)) (identifier))))))

=========================================
Inline method definitions
=========================================

struct S {
  int f;

  S() : f(0) {}

 private:
  int getF() const { return f; }
};

---

(translation_unit
  (struct_specifier (type_identifier) (field_declaration_list
    (field_declaration (primitive_type) (field_identifier))
    (function_definition
      (function_declarator (identifier) (parameter_list))
      (field_initializer_list (field_initializer (field_identifier) (argument_list (number_literal))))
      (compound_statement))
    (access_specifier)
    (function_definition
      (primitive_type)
      (function_declarator (field_identifier) (parameter_list) (type_qualifier))
      (compound_statement (return_statement (identifier)))))))

=========================================
Inline method definitions with overrides
=========================================

struct B : A {
  int foo() override { return 2; }
  int pho() final { return 3; }
  int bar() const override { return 4; }
  int baz() const final { return 5; }
  int bag() const final override { return 6; }
  int bah() const override final { return 7; }
};

---

(translation_unit
  (struct_specifier (type_identifier) (base_class_clause (type_identifier)) (field_declaration_list
    (function_definition
      (primitive_type)
      (function_declarator (field_identifier) (parameter_list) (virtual_specifier))
      (compound_statement (return_statement (number_literal))))
    (function_definition
      (primitive_type)
      (function_declarator (field_identifier) (parameter_list) (virtual_specifier))
      (compound_statement (return_statement (number_literal))))
    (function_definition
      (primitive_type)
      (function_declarator (field_identifier) (parameter_list) (type_qualifier) (virtual_specifier))
      (compound_statement (return_statement (number_literal))))
    (function_definition
      (primitive_type)
      (function_declarator (field_identifier) (parameter_list) (type_qualifier) (virtual_specifier))
      (compound_statement (return_statement (number_literal))))
    (function_definition
      (primitive_type)
      (function_declarator (field_identifier) (parameter_list) (type_qualifier) (virtual_specifier) (virtual_specifier))
      (compound_statement (return_statement (number_literal))))
    (function_definition
      (primitive_type)
      (function_declarator (field_identifier) (parameter_list) (type_qualifier) (virtual_specifier) (virtual_specifier))
      (compound_statement (return_statement (number_literal)))))))

=====================================
Virtual method declarations
===============================

class A {
  virtual ~Point();
  void b();
  virtual void foo() {}
  virtual void bar();
  inline virtual void foo() override;
  virtual inline void foo() final;
};

---

(translation_unit
  (class_specifier
    (type_identifier)
    (field_declaration_list
      (declaration
        (virtual_function_specifier)
        (function_declarator (destructor_name (identifier)) (parameter_list)))
      (field_declaration
        (primitive_type)
        (function_declarator (field_identifier) (parameter_list)))
      (function_definition
        (virtual_function_specifier)
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list))
        (compound_statement))
      (field_declaration
        (virtual_function_specifier)
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list)))
      (field_declaration
        (storage_class_specifier)
        (virtual_function_specifier)
        (primitive_type)
        (function_declarator (field_identifier) (parameter_list) (virtual_specifier)))
      (field_declaration
        (virtual_function_specifier)
        (storage_class_specifier)
        (primitive_type)
        (function_declarator (field_identifier) (parameter_list) (virtual_specifier))))))

=========================================
Constructor and destructor declarations
=========================================

class C {
  void *data_;

 public:
  C();
  C(int, float);
  inline C();
  explicit inline C();
  [[deprecated]] C();
  template <typename T>
  C(T t);
  C() : NS::Base<C>() {}
  ~C();
};

---

(translation_unit
  (class_specifier (type_identifier) (field_declaration_list
    (field_declaration (primitive_type) (pointer_declarator (field_identifier)))
    (access_specifier)
    (declaration (function_declarator (identifier) (parameter_list)))
    (declaration (function_declarator (identifier) (parameter_list
      (parameter_declaration (primitive_type))
      (parameter_declaration (primitive_type)))))
    (declaration (storage_class_specifier) (function_declarator (identifier) (parameter_list)))
    (declaration (explicit_function_specifier) (storage_class_specifier) (function_declarator (identifier) (parameter_list)))
    (declaration (attribute_declaration (attribute (identifier)))
      (function_declarator (identifier) (parameter_list)))
    (template_declaration (template_parameter_list (type_parameter_declaration (type_identifier)))
      (declaration (function_declarator (identifier) (parameter_list (parameter_declaration (type_identifier) (identifier))))))
    (function_definition (function_declarator (identifier) (parameter_list))
      (field_initializer_list
        (field_initializer
          (qualified_identifier
            (namespace_identifier) 
            (template_method
              (field_identifier)
              (template_argument_list (type_descriptor (type_identifier)))))
          (argument_list)))
      (compound_statement))
    (declaration (function_declarator (destructor_name (identifier)) (parameter_list))))))

=========================================
Classes with inheritance
=========================================

class A : public B {
};

class C : C::D, public E {
};

---

(translation_unit
  (class_specifier
    (type_identifier)
    (base_class_clause (type_identifier))
    (field_declaration_list))
  (class_specifier
    (type_identifier)
    (base_class_clause
      (qualified_identifier (namespace_identifier) (type_identifier))
      (type_identifier))
    (field_declaration_list)))

=========================================
Classes with final virt specifier
=========================================

class A final : public B {
};

class C final {};

struct D final {};

---

(translation_unit
  (class_specifier
    (type_identifier)
    (virtual_specifier)
    (base_class_clause (type_identifier))
    (field_declaration_list))
  (class_specifier
    (type_identifier)
    (virtual_specifier)
    (field_declaration_list))
  (struct_specifier
    (type_identifier)
    (virtual_specifier)
    (field_declaration_list)))

=========================================
Nested classes
========================================

class A {
 private:
  class B : private C, public D {
  };

  B e, f;
};

---

(translation_unit
  (class_specifier (type_identifier) (field_declaration_list
    (access_specifier)
    (field_declaration
      (class_specifier (type_identifier) (base_class_clause (type_identifier) (type_identifier)) (field_declaration_list)))
    (field_declaration
      (type_identifier) (field_identifier) (field_identifier)))))

=========================================
Friend declarations
=========================================

struct C {
  friend class D;
  friend D;
  friend int f(C &);
};

---

(translation_unit
  (struct_specifier (type_identifier) (field_declaration_list
    (friend_declaration (type_identifier))
    (friend_declaration (type_identifier))
    (friend_declaration (declaration (primitive_type) (function_declarator
      (identifier)
      (parameter_list (parameter_declaration (type_identifier) (abstract_reference_declarator)))))))))

=============================================
Default member initializers
=============================================

struct A {
  bool a = 1;
  vector<int> b = {c, d, e};
  F g {h};
};

---

(translation_unit
  (struct_specifier (type_identifier) (field_declaration_list
    (field_declaration
      (primitive_type)
      (field_identifier)
      (number_literal))
    (field_declaration
      (template_type (type_identifier) (template_argument_list (type_descriptor (primitive_type))))
      (field_identifier)
      (initializer_list (identifier) (identifier) (identifier)))
    (field_declaration
      (type_identifier)
      (field_identifier)
      (initializer_list (identifier))))))

=========================================
Function parameters with default values
=========================================

int foo(bool x = 5) {}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (optional_parameter_declaration (primitive_type) (identifier) (number_literal))))
    (compound_statement)))

=========================================
Attributes
=========================================

int f([[a::b(c), d]] int x) {}

[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]]
inline int g();

[[aaa]]
int f() { }

class [[gnu::visibility("default")]] A {};
struct [[gnu::visibility("default")]] A {};
union [[gnu::visibility("default")]] A {};

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list
        (parameter_declaration
          (attribute_declaration
            (attribute (identifier) (identifier) (argument_list (identifier)))
            (attribute (identifier)))
          (primitive_type)
          (identifier))))
    (compound_statement))
  (declaration
    (attribute_declaration (attribute (identifier) (identifier)))
    (attribute_declaration (attribute (identifier) (identifier)))
    (attribute_declaration (attribute (identifier) (identifier)))
    (attribute_declaration (attribute (identifier)))
    (storage_class_specifier)
    (primitive_type)
    (function_declarator (identifier) (parameter_list)))
  (function_definition
    (attribute_declaration (attribute (identifier)))
    (primitive_type) (function_declarator (identifier) (parameter_list)) (compound_statement))
  (class_specifier
    (attribute_declaration (attribute (identifier) (identifier) (argument_list (string_literal))))
    (type_identifier)
    (field_declaration_list))
  (struct_specifier
    (attribute_declaration (attribute (identifier) (identifier) (argument_list (string_literal))))
    (type_identifier)
    (field_declaration_list))
  (union_specifier
    (attribute_declaration (attribute (identifier) (identifier) (argument_list (string_literal))))
    (type_identifier)
    (field_declaration_list)))

=========================================
Operator overload declarations
=========================================

ostream &operator<<(ostream &, const A &a);
Foo operator "" _foo(const char* s);
std::string_view operator ""s_v(const char* s);
bool A::operator!=(const A &other) const;

bool A::operator ==(const A &other) const;

void * A::operator new(size_t s);

void * A::operator delete   [](void * p);

---

(translation_unit
  (declaration
    (type_identifier)
    (reference_declarator
      (function_declarator
        (operator_name)
        (parameter_list
          (parameter_declaration (type_identifier) (abstract_reference_declarator))
          (parameter_declaration (type_qualifier) (type_identifier) (reference_declarator (identifier)))))))
  (declaration
    (type_identifier)
    (function_declarator
      (operator_name (identifier))
      (parameter_list
        (parameter_declaration (type_qualifier) (primitive_type) (pointer_declarator (identifier))))))
  (declaration
    (qualified_identifier (namespace_identifier) (type_identifier))
    (function_declarator
      (operator_name (identifier))
      (parameter_list
        (parameter_declaration (type_qualifier) (primitive_type) (pointer_declarator (identifier))))))
  (declaration
    (primitive_type)
    (function_declarator
      (qualified_identifier (namespace_identifier) (operator_name))
      (parameter_list
        (parameter_declaration (type_qualifier) (type_identifier) (reference_declarator (identifier))))
      (type_qualifier)))
  (declaration
    (primitive_type)
    (function_declarator
      (qualified_identifier (namespace_identifier) (operator_name))
      (parameter_list
        (parameter_declaration (type_qualifier) (type_identifier) (reference_declarator (identifier))))
      (type_qualifier)))
   (declaration
     (primitive_type)
     (pointer_declarator
       (function_declarator
         (qualified_identifier (namespace_identifier) (operator_name))
         (parameter_list (parameter_declaration (primitive_type) (identifier))))))
   (declaration
     (primitive_type)
     (pointer_declarator
       (function_declarator
         (qualified_identifier (namespace_identifier) (operator_name))
         (parameter_list (parameter_declaration (primitive_type) (pointer_declarator (identifier))))))))

=========================================
Template declarations
=========================================

template <typename T>
void foo(T &t);

template <typename T, int u>
int bar(T &t) { return u; }

template <typename T>
class Foo {};

template <typename T>
Foo<T>::Foo(int mem) : mem_(mem) {}

template <typename T>
template <typename U>
void A<T>::foo(U&) {}

---

(translation_unit
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration (type_identifier)))
    (declaration
      (primitive_type)
      (function_declarator
        (identifier)
        (parameter_list
          (parameter_declaration (type_identifier) (reference_declarator (identifier)))))))
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration (type_identifier))
      (parameter_declaration (primitive_type) (identifier)))
    (function_definition
      (primitive_type)
      (function_declarator
        (identifier)
        (parameter_list (parameter_declaration (type_identifier) (reference_declarator (identifier)))))
      (compound_statement (return_statement (identifier)))))
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration (type_identifier)))
    (class_specifier (type_identifier) (field_declaration_list)))
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration (type_identifier)))
    (function_definition
      (function_declarator
        (qualified_identifier
          (template_type
            (type_identifier)
            (template_argument_list (type_descriptor (type_identifier))))
          (identifier))
        (parameter_list
          (parameter_declaration (primitive_type) (identifier))))
      (field_initializer_list
        (field_initializer
          (field_identifier)
          (argument_list (identifier))))
      (compound_statement)))
  (template_declaration
    (template_parameter_list
      (type_parameter_declaration (type_identifier)))
    (template_declaration
      (template_parameter_list
        (type_parameter_declaration (type_identifier)))
      (function_definition
        (primitive_type)
        (function_declarator
          (qualified_identifier
            (template_type
              (type_identifier)
              (template_argument_list (type_descriptor (type_identifier))))
            (identifier))
          (parameter_list
            (parameter_declaration
              (type_identifier)
              (abstract_reference_declarator))))
        (compound_statement)))))

=========================================
Template template declarations
=========================================

template <template <typename> typename T>
void foo() {}

template <template <typename...> class>
void bar() {}

template <template <typename> typename...>
void baz() {}

---

(translation_unit
  (template_declaration
    (template_parameter_list
      (template_template_parameter_declaration
        (template_parameter_list (type_parameter_declaration))
        (type_parameter_declaration (type_identifier))))
    (function_definition
      (primitive_type)
      (function_declarator
        (identifier)
        (parameter_list))
      (compound_statement)))
  (template_declaration
    (template_parameter_list
      (template_template_parameter_declaration
        (template_parameter_list (variadic_type_parameter_declaration))
        (type_parameter_declaration)))
    (function_definition
      (primitive_type)
      (function_declarator
        (identifier)
        (parameter_list))
      (compound_statement)))
  (template_declaration
    (template_parameter_list
      (template_template_parameter_declaration
        (template_parameter_list (type_parameter_declaration))
        (variadic_type_parameter_declaration)))
    (function_definition
      (primitive_type)
      (function_declarator
        (identifier)
        (parameter_list))
      (compound_statement))))

=========================================
Template specializations
=========================================

template <>
void foo<T>(T &t);

template <>
struct foo::bar<T> {};

---

(translation_unit
  (template_declaration
    (template_parameter_list)
    (declaration
      (primitive_type)
      (function_declarator
        (template_function
          (identifier)
          (template_argument_list (type_descriptor (type_identifier))))
        (parameter_list
          (parameter_declaration (type_identifier) (reference_declarator (identifier)))))))
  (template_declaration
    (template_parameter_list)
    (struct_specifier
      (qualified_identifier
        (namespace_identifier)
        (template_type
          (type_identifier)
          (template_argument_list (type_descriptor (type_identifier)))))
      (field_declaration_list))))

====================================================
Template methods
====================================================

class Person {
  Person() {
    this->speak<int>();
  }

  template <typename T>
  void speak() {}

  template <>
  void speak<bool>() {}
};

---

(translation_unit
  (class_specifier (type_identifier) (field_declaration_list
    (function_definition
      (function_declarator (identifier) (parameter_list))
      (compound_statement
        (expression_statement (call_expression
          (field_expression
            (this)
            (template_method
              (field_identifier)
              (template_argument_list (type_descriptor (primitive_type)))))
          (argument_list)))))
    (template_declaration
      (template_parameter_list (type_parameter_declaration (type_identifier)))
      (function_definition
        (primitive_type)
        (function_declarator
          (identifier)
          (parameter_list))
        (compound_statement)))
    (template_declaration
      (template_parameter_list)
      (function_definition
        (primitive_type)
        (function_declarator
          (template_function (identifier) (template_argument_list (type_descriptor (primitive_type))))
          (parameter_list))
        (compound_statement))))))

==========================================
Templates with optional type parameters
==========================================

template <typename T = U::V<void>>
class X
{
};

template <typename = void>
class Y
{
};

---

(translation_unit
  (template_declaration
    parameters: (template_parameter_list
      (optional_type_parameter_declaration
        name: (type_identifier)
        default_type: (qualified_identifier
            scope: (namespace_identifier)
            name: (template_type
              name: (type_identifier)
              arguments: (template_argument_list
                (type_descriptor type: (primitive_type)))))))
    (class_specifier
      name: (type_identifier)
      body: (field_declaration_list)))
  (template_declaration
    parameters: (template_parameter_list
      (optional_type_parameter_declaration
        default_type: (primitive_type)))
    (class_specifier
      name: (type_identifier)
      body: (field_declaration_list))))

==============================================
Templates with optional anonymous parameters
==============================================

template <class T, typename a::b<!c<T>{} && (d<T>{} || e<T>{})>::type = 0>
class X
{
};

---

(translation_unit
  (template_declaration
    parameters: (template_parameter_list
      (type_parameter_declaration (type_identifier))
      (optional_parameter_declaration
        type: (dependent_type (qualified_identifier
          scope: (namespace_identifier)
          name:  (qualified_identifier
            scope: (template_type
              name: (type_identifier)
              arguments: (template_argument_list
                (binary_expression
                  left: (unary_expression
                    argument: (compound_literal_expression
                      type: (template_type
                        name: (type_identifier)
                        arguments: (template_argument_list (type_descriptor type: (type_identifier))))
                      value: (initializer_list)))
                  right: (parenthesized_expression
                    (binary_expression
                      left: (compound_literal_expression
                        type: (template_type
                          name: (type_identifier)
                          arguments: (template_argument_list (type_descriptor type: (type_identifier))))
                        value: (initializer_list))
                      right: (compound_literal_expression
                        type: (template_type
                          name: (type_identifier)
                          arguments: (template_argument_list (type_descriptor type: (type_identifier))))
                        value: (initializer_list)))))))
        name: (type_identifier))))
      default_value: (number_literal)))
    (class_specifier
      name: (type_identifier)
      body: (field_declaration_list))))

==========================================
Declarations with braced initializer lists
==========================================

A foo{1, 2};

---

(translation_unit
  (declaration
    (type_identifier)
    (init_declarator (identifier) (initializer_list (number_literal) (number_literal)))))

===========================================
Empty function bodies
===========================================

int main() {}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator (identifier) (parameter_list))
    (compound_statement)))

==========================================
Explicit template instantiations
==========================================

template A<int, bool>::A(char *, size_t);

---

(translation_unit
  (template_instantiation
    (function_declarator
      (qualified_identifier
        (template_type
          (type_identifier)
          (template_argument_list
            (type_descriptor (primitive_type))
            (type_descriptor (primitive_type))))
        (identifier))
      (parameter_list
        (parameter_declaration (primitive_type) (abstract_pointer_declarator))
        (parameter_declaration (primitive_type))))))

=====================================
Structured binding declarations
=====================================

auto [a] = B{};

int main() {
  auto &&[b, c] = std::make_tuple(c);
  const auto [x, y] {1, 2};

  for (const auto &[a, b] : c) {}
}

---

(translation_unit
  (declaration
    type: (placeholder_type_specifier (auto))
    declarator: (init_declarator
      declarator: (structured_binding_declarator (identifier))
      value: (compound_literal_expression
        type: (type_identifier)
        value: (initializer_list))))
  (function_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))
    body: (compound_statement
      (declaration
        type: (placeholder_type_specifier (auto))
        declarator: (init_declarator
          declarator: (reference_declarator
            (structured_binding_declarator (identifier) (identifier)))
          value: (call_expression
            function: (qualified_identifier
              scope: (namespace_identifier)
              name: (identifier))
            arguments: (argument_list (identifier)))))
      (declaration
        (type_qualifier)
        type: (placeholder_type_specifier (auto))
        declarator: (init_declarator
          declarator: (structured_binding_declarator (identifier) (identifier))
          value: (initializer_list (number_literal) (number_literal))))
      (for_range_loop
        (type_qualifier)
        type: (placeholder_type_specifier (auto))
        declarator: (reference_declarator (structured_binding_declarator
          (identifier)
          (identifier)))
        right: (identifier)
        body: (compound_statement)))))

==========================
Constexpr/constinit/consteval declarations
==========================

constexpr double pi = 3.14159;
consteval int answer();
constinit int life = answer();

---

(translation_unit
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (identifier)
      (number_literal)))
  (declaration
    (type_qualifier)
    (primitive_type)
    (function_declarator
      (identifier)
      (parameter_list)))
  (declaration
    (type_qualifier)
    (primitive_type)
    (init_declarator
      (identifier)
      (call_expression
        (identifier)
        (argument_list)))))

============================
Variadic templates
============================

template <class T>
class TT {
  template <typename... Ts>
  void func1(Ts ... args) {
    func3(nullptr);
  }

  void func2(Ts &&... args) {}

  template <typename...>
  void func3() {}

  template <std::size_t...>
  void func4() {}
};

---

(translation_unit
  (template_declaration
    (template_parameter_list (type_parameter_declaration (type_identifier)))
    (class_specifier (type_identifier) (field_declaration_list
      (template_declaration
        (template_parameter_list (variadic_type_parameter_declaration (type_identifier)))
        (function_definition
          (primitive_type)
          (function_declarator
            (identifier)
            (parameter_list
              (variadic_parameter_declaration
                (type_identifier)
                (variadic_declarator (identifier)))))
          (compound_statement
            (expression_statement (call_expression (identifier) (argument_list (nullptr)))))))
        (function_definition
          (primitive_type)
          (function_declarator
            (field_identifier)
            (parameter_list
              (variadic_parameter_declaration
                (type_identifier)
                (reference_declarator (variadic_declarator (identifier))))))
          (compound_statement))
        (template_declaration
          (template_parameter_list (variadic_type_parameter_declaration))
          (function_definition
            (primitive_type)
            (function_declarator
              (identifier)
              (parameter_list))
            (compound_statement)))
        (template_declaration
          (template_parameter_list
            (variadic_parameter_declaration
              (qualified_identifier
                (namespace_identifier)
                (type_identifier))
              (variadic_declarator)))
          (function_definition
            (primitive_type)
            (function_declarator
              (identifier)
              (parameter_list))
            (compound_statement)))))))

============================
Enums
============================

enum Foo : char { };
enum Foo : Bar { };
enum Foo : unsigned int { };
enum {a, b};
enum Foo : Bar::Rab { };
enum Foo::Oof : Bar::Rab { };
enum class Foo;
enum struct Foo : char { };

---

(translation_unit
  (enum_specifier (type_identifier) (type_identifier) (enumerator_list))
  (enum_specifier (type_identifier) (type_identifier) (enumerator_list))
  (enum_specifier (type_identifier) (sized_type_specifier (primitive_type)) (enumerator_list))
  (enum_specifier (enumerator_list (enumerator (identifier)) (enumerator (identifier))))
  (enum_specifier (type_identifier) (qualified_identifier (namespace_identifier) (type_identifier)) (enumerator_list))
  (enum_specifier (qualified_identifier (namespace_identifier) (type_identifier)) (qualified_identifier (namespace_identifier) (type_identifier)) (enumerator_list))
  (enum_specifier (type_identifier))
  (enum_specifier (type_identifier) (type_identifier) (enumerator_list)))

============================
static_assert declarations
============================

class A { static_assert(true, "message"); };
void f() { static_assert(false); }
static_assert(std::is_constructible<A>::value);
static_assert(true, "string1" "string2");
static_assert(true, R"FOO(string)FOO");

---

(translation_unit
  (class_specifier
    name: (type_identifier)
    body: (field_declaration_list
    (static_assert_declaration
      condition: (true)
      message: (string_literal))))
  (function_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))
    body: (compound_statement
      (static_assert_declaration
        condition: (false))))
  (static_assert_declaration
    condition: (qualified_identifier
      scope: (namespace_identifier)
      name: (qualified_identifier
        scope: (template_type
          name: (type_identifier)
          arguments: (template_argument_list
            (type_descriptor type: (type_identifier))))
        name: (identifier))))
  (static_assert_declaration
    condition: (true)
    message: (concatenated_string (string_literal) (string_literal)))
  (static_assert_declaration
    condition: (true)
    message: (raw_string_literal)))

=========================================
Cast operator overload declarations
=========================================

operator int() const;
explicit operator int*() const;
operator arr_t*();
operator B&();
operator auto() const;
virtual operator A() = 0;
A::B::operator C();
template <typename T>
operator T*();
[[nodiscard]] operator char *();

---

(translation_unit
  (declaration
    (operator_cast
      (primitive_type)
      (abstract_function_declarator (parameter_list) (type_qualifier))))
  (declaration
    (explicit_function_specifier)
    (operator_cast
      (primitive_type)
      (abstract_pointer_declarator (abstract_function_declarator (parameter_list) (type_qualifier)))))
  (declaration
    (operator_cast
      (type_identifier)
      (abstract_pointer_declarator (abstract_function_declarator (parameter_list)))))
  (declaration (operator_cast
    (type_identifier)
    (abstract_reference_declarator (abstract_function_declarator (parameter_list)))))
  (declaration
    (operator_cast
      (placeholder_type_specifier (auto))
      (abstract_function_declarator (parameter_list) (type_qualifier))))
  (declaration
    (virtual_function_specifier)
    (operator_cast (type_identifier) (abstract_function_declarator (parameter_list))) (number_literal))
  (declaration
    (qualified_identifier
      (namespace_identifier)
      (qualified_identifier
        (namespace_identifier)
        (operator_cast
          (type_identifier)
          (abstract_function_declarator (parameter_list))))))
  (template_declaration
    (template_parameter_list (type_parameter_declaration (type_identifier)))
    (declaration (operator_cast
      (type_identifier)
      (abstract_pointer_declarator (abstract_function_declarator (parameter_list))))))
  (declaration
    (attribute_declaration (attribute (identifier)))
    (operator_cast (primitive_type) (abstract_pointer_declarator (abstract_function_declarator (parameter_list))))))

=========================================
Class scope cast operator overload declarations
=========================================

class A {
  operator int() const {}
  explicit operator int*() const;
  operator arr_t*();
  operator B&();
  operator auto() const;
  virtual operator A() = 0;
  A::B::operator C();
  template <typename T>
  operator T*();
  [[nodiscard]] operator char *();
};

---

(translation_unit
  (class_specifier (type_identifier) (field_declaration_list
    (function_definition
      (operator_cast
        (primitive_type)
        (abstract_function_declarator (parameter_list) (type_qualifier)))
      (compound_statement))
    (declaration
      (explicit_function_specifier)
      (operator_cast
        (primitive_type)
        (abstract_pointer_declarator (abstract_function_declarator (parameter_list) (type_qualifier)))))
    (declaration
      (operator_cast
        (type_identifier)
        (abstract_pointer_declarator (abstract_function_declarator (parameter_list)))))
    (declaration (operator_cast
      (type_identifier)
      (abstract_reference_declarator (abstract_function_declarator (parameter_list)))))
    (declaration
      (operator_cast
        (placeholder_type_specifier (auto))
        (abstract_function_declarator (parameter_list) (type_qualifier))))
    (declaration
      (virtual_function_specifier)
      (operator_cast (type_identifier) (abstract_function_declarator (parameter_list))) (number_literal))
    (declaration
      (qualified_identifier
        (namespace_identifier)
        (qualified_identifier
          (namespace_identifier)
          (operator_cast
            (type_identifier)
            (abstract_function_declarator (parameter_list))))))
    (template_declaration
      (template_parameter_list (type_parameter_declaration (type_identifier)))
      (declaration (operator_cast
        (type_identifier)
        (abstract_pointer_declarator (abstract_function_declarator (parameter_list))))))
    (declaration
      (attribute_declaration (attribute (identifier)))
      (operator_cast (primitive_type) (abstract_pointer_declarator (abstract_function_declarator (parameter_list))))))))

=========================
Function declarations
=========================

inline int g();
inline int h() { }

---

(translation_unit
  (declaration
    (storage_class_specifier)
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list)))
  (function_definition
    (storage_class_specifier)
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list))
    body: (compound_statement)))

============================================
Variable storage classes
============================================

int a;
extern int b, c;
register int e;
static int f;
thread_local int c;

---

(translation_unit
  (declaration (primitive_type) (identifier))
  (declaration (storage_class_specifier) (primitive_type) (identifier) (identifier))
  (declaration (storage_class_specifier) (primitive_type) (identifier))
  (declaration (storage_class_specifier) (primitive_type) (identifier))
  (declaration (storage_class_specifier) (primitive_type) (identifier)))

=========================
Ref-qualifiers
=========================

class C
{
  void f() &;
  void f() && noexcept;
  void f() & {}
  void f() & noexcept {}
};

void C::f() &;
void C::f() & noexcept;
void C::f() && {}
void C::f() & noexcept {}

---

(translation_unit
  (class_specifier
    (type_identifier)
    (field_declaration_list
      (field_declaration
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list)
          (ref_qualifier)))
      (field_declaration
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list)
          (ref_qualifier)
          (noexcept)))
      (function_definition
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list)
          (ref_qualifier))
        (compound_statement))
      (function_definition
        (primitive_type)
        (function_declarator
          (field_identifier)
          (parameter_list)
          (ref_qualifier)
          (noexcept))
        (compound_statement))))
  (declaration
    (primitive_type)
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (identifier))
      (parameter_list)
      (ref_qualifier)))
  (declaration
    (primitive_type)
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (identifier))
      (parameter_list)
      (ref_qualifier)
      (noexcept)))
  (function_definition
    (primitive_type)
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (identifier))
      (parameter_list)
      (ref_qualifier))
    (compound_statement))
  (function_definition
    (primitive_type)
    (function_declarator
      (qualified_identifier
        (namespace_identifier)
        (identifier))
      (parameter_list)
      (ref_qualifier)
      (noexcept))
    (compound_statement)))

=========================
Default comparison declarations
=========================

struct A {
    auto operator<=>(A const &) = default;
    friend auto operator<=>(A const &, A const &) = default;
};

---

(translation_unit
  (struct_specifier
    (type_identifier)
    (field_declaration_list
      (function_definition
        (placeholder_type_specifier (auto))
        (function_declarator
          (operator_name)
          (parameter_list
            (parameter_declaration
              (type_identifier)
              (type_qualifier)
              (abstract_reference_declarator))))
        (default_method_clause))
      (friend_declaration
        (declaration
          (placeholder_type_specifier (auto))
          (init_declarator
            (function_declarator
              (operator_name)
              (parameter_list
                (parameter_declaration
                  (type_identifier)
                  (type_qualifier)
                  (abstract_reference_declarator))
                (parameter_declaration
                  (type_identifier)
                  (type_qualifier)
                  (abstract_reference_declarator))))
            (identifier)))))))
