Repository: Qiskit/qiskit-terra (python)

Issue:
qasm3 exporter wrong placement of `input` declaration
### Environment

- **Qiskit Terra version**: 0.20.0
- **Python version**: 3.8.13
- **Operating system**: macOS Monterey 12.3.1


### What is happening?

When exporting parametrized `QuantumCircuit`s with custom gates to a QASM3 string, the exporter wrongly places the circuit's `input` declaration after the `gate` declarations, which is not according to the OpenQASM3.0 grammar - IO declarations should appear in the [header](https://github.com/Qiskit/openqasm/blob/c39eac9f5c87b80df9e8eaeced96cbf4b477e5d2/source/grammar/qasm3.g4#L12).

### How can we reproduce the issue?

Run the following:

```python
from qiskit import QuantumCircuit, qasm3
from qiskit.circuit import Parameter

theta = Parameter("theta")
inner_qc = QuantumCircuit(1)
inner_qc.rz(theta, 0)
qc = QuantumCircuit(1)
qc.append(inner_qc.to_gate(), range(1))
print(qasm3.dumps(qc))
```
The resulting OpenQASM3.0 code is then:
```qasm
OPENQASM 3;
include "stdgates.inc";
gate circuit_21(theta) _gate_q_0 {
  rz(theta) _gate_q_0;
}
input float[64] theta;
qubit[1] _all_qubits;
let q = _all_qubits[0:0];
circuit_21(theta) q[0];
```

### What should happen?

The expected output according to the grammar is:
```qasm
OPENQASM 3;
include "stdgates.inc";
input float[64] theta;
gate circuit_21(theta) _gate_q_0 {
  rz(theta) _gate_q_0;
}
qubit[1] _all_qubits;
let q = _all_qubits[0:0];
circuit_21(theta) q[0];
```

### Any suggestions?

_No response_

Pull request:
Fix order of input and gate declarations in QASM 3 exporter
### Summary

The current reference grammar requires that inputs and outputs are
defined before any gate declarations, so previously exported OpenQASM 3
programmes could fail to parse with the reference implementation.  It is
likely that the ordering is an arbitrary restriction and can be removed
from the grammar, but for the time being, we ought to match what is
written.

<!--
⚠️ If you do not respect this template, your pull request will be closed.
⚠️ Your pull request title should be short detailed and understandable for all.
⚠️ Also, please add a release note file using reno if the change needs to be
  documented in the release notes.
⚠️ If your pull request fixes an open issue, please link to the issue.

- [ ] I have added the tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->


### Details and comments

Fix #7964.


Patch:
diff --git a/qiskit/qasm3/exporter.py b/qiskit/qasm3/exporter.py
index 759783d0c..1d54b58b9 100644
--- a/qiskit/qasm3/exporter.py
+++ b/qiskit/qasm3/exporter.py
@@ -532,9 +532,9 @@ class QASM3Builder:
         return [
             statement
             for source in (
-                definitions,
                 inputs,
                 outputs,
+                definitions,
                 variables,
                 bit_declarations,
                 quantum_declarations,
diff --git a/releasenotes/notes/fix-qasm3-global-statement-order-ca8bdb35e0fb8dec.yaml b/releasenotes/notes/fix-qasm3-global-statement-order-ca8bdb35e0fb8dec.yaml
new file mode 100644
index 000000000..d5debf9f9
--- /dev/null
+++ b/releasenotes/notes/fix-qasm3-global-statement-order-ca8bdb35e0fb8dec.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+  - |
+    The OpenQASM 3 exporter (:mod:`qiskit.qasm3`) will now output ``input`` or
+    ``output`` declarations before gate declarations.  This is more consistent
+    with the current reference ANTLR grammar from the OpenQASM 3 team.


Test patch:
diff --git a/test/python/circuit/test_circuit_qasm3.py b/test/python/circuit/test_circuit_qasm3.py
index be71898a6..e5dff6a25 100644
--- a/test/python/circuit/test_circuit_qasm3.py
+++ b/test/python/circuit/test_circuit_qasm3.py
@@ -368,10 +368,10 @@ class TestCircuitQASM3(QiskitTestCase):
             [
                 "OPENQASM 3;",
                 'include "stdgates.inc";',
+                "input float[64] a;",
                 "gate custom(a) _gate_q_0 {",
                 "  rx(a) _gate_q_0;",
                 "}",
-                "input float[64] a;",
                 "qubit[1] _all_qubits;",
                 "let q = _all_qubits[0:0];",
                 "custom(a) q[0];",
@@ -504,6 +504,8 @@ class TestCircuitQASM3(QiskitTestCase):
         expected_qasm = "\n".join(
             [
                 "OPENQASM 3;",
+                "input float[64] x;",
+                "input float[64] y;",
                 "gate rzx(x) _gate_q_0, _gate_q_1 {",
                 "  h _gate_q_1;",
                 "  cx _gate_q_0, _gate_q_1;",
@@ -511,8 +513,6 @@ class TestCircuitQASM3(QiskitTestCase):
                 "  cx _gate_q_0, _gate_q_1;",
                 "  h _gate_q_1;",
                 "}",
-                "input float[64] x;",
-                "input float[64] y;",
                 "qubit[2] _all_qubits;",
                 "let q = _all_qubits[0:1];",
                 "rzx(x) q[0], q[1];",