1261 lines
45 KiB
Python
1261 lines
45 KiB
Python
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
|
|
|
from cxxheaderparser.types import (
|
|
Array,
|
|
AutoSpecifier,
|
|
ClassDecl,
|
|
DecltypeSpecifier,
|
|
Field,
|
|
Function,
|
|
FunctionType,
|
|
FundamentalSpecifier,
|
|
Method,
|
|
MoveReference,
|
|
NameSpecifier,
|
|
PQName,
|
|
Parameter,
|
|
Pointer,
|
|
Reference,
|
|
TemplateArgument,
|
|
TemplateDecl,
|
|
TemplateSpecialization,
|
|
TemplateTypeParam,
|
|
Token,
|
|
Type,
|
|
Typedef,
|
|
Value,
|
|
)
|
|
from cxxheaderparser.simple import (
|
|
ClassScope,
|
|
NamespaceScope,
|
|
parse_string,
|
|
ParsedData,
|
|
)
|
|
|
|
|
|
def test_fn_returns_class() -> None:
|
|
content = """
|
|
class X *fn1();
|
|
struct Y fn2();
|
|
enum E fn3();
|
|
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[NameSpecifier(name="X")], classkey="class"
|
|
)
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn1")]),
|
|
parameters=[],
|
|
),
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[NameSpecifier(name="Y")], classkey="struct"
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn2")]),
|
|
parameters=[],
|
|
),
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[NameSpecifier(name="E")], classkey="enum"
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn3")]),
|
|
parameters=[],
|
|
),
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_returns_typename() -> None:
|
|
content = """
|
|
typename ns::X fn();
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(name="ns"),
|
|
NameSpecifier(name="X"),
|
|
],
|
|
has_typename=True,
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
|
parameters=[],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_returns_typename_const() -> None:
|
|
content = """
|
|
const typename ns::X fn();
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(name="ns"),
|
|
NameSpecifier(name="X"),
|
|
],
|
|
has_typename=True,
|
|
),
|
|
const=True,
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
|
parameters=[],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_pointer_params() -> None:
|
|
content = """
|
|
int fn1(int *);
|
|
int fn2(int *p);
|
|
int fn3(int(*p));
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn1")]),
|
|
parameters=[
|
|
Parameter(
|
|
type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
)
|
|
)
|
|
),
|
|
)
|
|
],
|
|
),
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn2")]),
|
|
parameters=[
|
|
Parameter(
|
|
name="p",
|
|
type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
)
|
|
)
|
|
),
|
|
)
|
|
],
|
|
),
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn3")]),
|
|
parameters=[
|
|
Parameter(
|
|
name="p",
|
|
type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
)
|
|
)
|
|
),
|
|
)
|
|
],
|
|
),
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_void_is_no_params() -> None:
|
|
content = """
|
|
int fn(void);
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
|
parameters=[],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_array_param() -> None:
|
|
content = """
|
|
void fn(int array[]);
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
|
parameters=[
|
|
Parameter(
|
|
name="array",
|
|
type=Array(
|
|
array_of=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
)
|
|
),
|
|
size=None,
|
|
),
|
|
)
|
|
],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_typename_param() -> None:
|
|
content = """
|
|
void MethodA(const mynamespace::SomeObject &x,
|
|
typename mynamespace::SomeObject * = 0);
|
|
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="MethodA")]),
|
|
parameters=[
|
|
Parameter(
|
|
type=Reference(
|
|
ref_to=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(name="mynamespace"),
|
|
NameSpecifier(name="SomeObject"),
|
|
]
|
|
),
|
|
const=True,
|
|
)
|
|
),
|
|
name="x",
|
|
),
|
|
Parameter(
|
|
type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(name="mynamespace"),
|
|
NameSpecifier(name="SomeObject"),
|
|
],
|
|
has_typename=True,
|
|
)
|
|
)
|
|
),
|
|
default=Value(tokens=[Token(value="0")]),
|
|
),
|
|
],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_weird_refs() -> None:
|
|
content = """
|
|
int aref(int(&x));
|
|
void ptr_ref(int(*&name));
|
|
void ref_to_array(int (&array)[]);
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="aref")]),
|
|
parameters=[
|
|
Parameter(
|
|
name="x",
|
|
type=Reference(
|
|
ref_to=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
)
|
|
)
|
|
),
|
|
)
|
|
],
|
|
),
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="ptr_ref")]),
|
|
parameters=[
|
|
Parameter(
|
|
name="name",
|
|
type=Reference(
|
|
ref_to=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
)
|
|
)
|
|
)
|
|
),
|
|
)
|
|
],
|
|
),
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="ref_to_array")]),
|
|
parameters=[
|
|
Parameter(
|
|
name="array",
|
|
type=Reference(
|
|
ref_to=Array(
|
|
array_of=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
)
|
|
),
|
|
size=None,
|
|
)
|
|
),
|
|
)
|
|
],
|
|
),
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_too_many_parens() -> None:
|
|
content = """
|
|
int fn1(int (x));
|
|
void (fn2 (int (*const (name))));
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn1")]),
|
|
parameters=[
|
|
Parameter(
|
|
name="x",
|
|
type=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
)
|
|
),
|
|
)
|
|
],
|
|
),
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn2")]),
|
|
parameters=[
|
|
Parameter(
|
|
name="name",
|
|
type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
)
|
|
),
|
|
const=True,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
# TODO calling conventions
|
|
"""
|
|
void __stdcall fn();
|
|
void (__stdcall * fn)
|
|
"""
|
|
|
|
|
|
def test_fn_same_line() -> None:
|
|
# multiple functions on the same line
|
|
content = """
|
|
void fn1(), fn2();
|
|
void *fn3(), fn4();
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn1")]),
|
|
parameters=[],
|
|
),
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn2")]),
|
|
parameters=[],
|
|
),
|
|
Function(
|
|
return_type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="void")]
|
|
)
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn3")]),
|
|
parameters=[],
|
|
),
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn4")]),
|
|
parameters=[],
|
|
),
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_auto_template() -> None:
|
|
content = """
|
|
template<class T, class U>
|
|
auto add(T t, U u) { return t + u; }
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(typename=PQName(segments=[AutoSpecifier()])),
|
|
name=PQName(segments=[NameSpecifier(name="add")]),
|
|
parameters=[
|
|
Parameter(
|
|
type=Type(
|
|
typename=PQName(segments=[NameSpecifier(name="T")])
|
|
),
|
|
name="t",
|
|
),
|
|
Parameter(
|
|
type=Type(
|
|
typename=PQName(segments=[NameSpecifier(name="U")])
|
|
),
|
|
name="u",
|
|
),
|
|
],
|
|
has_body=True,
|
|
template=TemplateDecl(
|
|
params=[
|
|
TemplateTypeParam(typekey="class", name="T"),
|
|
TemplateTypeParam(typekey="class", name="U"),
|
|
]
|
|
),
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_template_ptr() -> None:
|
|
content = """
|
|
std::vector<Pointer *> *fn(std::vector<Pointer *> *ps);
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(name="std"),
|
|
NameSpecifier(
|
|
name="vector",
|
|
specialization=TemplateSpecialization(
|
|
args=[
|
|
TemplateArgument(
|
|
arg=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(
|
|
name="Pointer"
|
|
)
|
|
]
|
|
)
|
|
)
|
|
)
|
|
)
|
|
]
|
|
),
|
|
),
|
|
]
|
|
)
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
|
parameters=[
|
|
Parameter(
|
|
type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(name="std"),
|
|
NameSpecifier(
|
|
name="vector",
|
|
specialization=TemplateSpecialization(
|
|
args=[
|
|
TemplateArgument(
|
|
arg=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(
|
|
name="Pointer"
|
|
)
|
|
]
|
|
)
|
|
)
|
|
)
|
|
)
|
|
]
|
|
),
|
|
),
|
|
]
|
|
)
|
|
)
|
|
),
|
|
name="ps",
|
|
)
|
|
],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_with_impl() -> None:
|
|
content = """
|
|
// clang-format off
|
|
void termite(void)
|
|
{
|
|
return ((structA*) (Func())->element);
|
|
}
|
|
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="termite")]),
|
|
parameters=[],
|
|
has_body=True,
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_return_std_function() -> None:
|
|
content = """
|
|
std::function<void(int)> fn();
|
|
"""
|
|
data1 = parse_string(content, cleandoc=True)
|
|
|
|
content = """
|
|
std::function<void((int))> fn();
|
|
"""
|
|
data2 = parse_string(content, cleandoc=True)
|
|
|
|
expected = ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(name="std"),
|
|
NameSpecifier(
|
|
name="function",
|
|
specialization=TemplateSpecialization(
|
|
args=[
|
|
TemplateArgument(
|
|
arg=FunctionType(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
FundamentalSpecifier(
|
|
name="void"
|
|
)
|
|
]
|
|
)
|
|
),
|
|
parameters=[
|
|
Parameter(
|
|
type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
FundamentalSpecifier(
|
|
name="int"
|
|
)
|
|
]
|
|
)
|
|
)
|
|
)
|
|
],
|
|
)
|
|
)
|
|
]
|
|
),
|
|
),
|
|
]
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
|
parameters=[],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
assert data1 == expected
|
|
assert data2 == expected
|
|
|
|
|
|
def test_fn_return_std_function_trailing() -> None:
|
|
content = """
|
|
std::function<auto(int)->int> fn();
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(name="std"),
|
|
NameSpecifier(
|
|
name="function",
|
|
specialization=TemplateSpecialization(
|
|
args=[
|
|
TemplateArgument(
|
|
arg=FunctionType(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
FundamentalSpecifier(
|
|
name="int"
|
|
)
|
|
]
|
|
)
|
|
),
|
|
parameters=[
|
|
Parameter(
|
|
type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
FundamentalSpecifier(
|
|
name="int"
|
|
)
|
|
]
|
|
)
|
|
)
|
|
)
|
|
],
|
|
has_trailing_return=True,
|
|
)
|
|
)
|
|
]
|
|
),
|
|
),
|
|
]
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
|
parameters=[],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_trailing_return_simple() -> None:
|
|
content = """
|
|
auto fn() -> int;
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
|
parameters=[],
|
|
has_trailing_return=True,
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_trailing_return_std_function() -> None:
|
|
content = """
|
|
auto fn() -> std::function<int()>;
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(name="std"),
|
|
NameSpecifier(
|
|
name="function",
|
|
specialization=TemplateSpecialization(
|
|
args=[
|
|
TemplateArgument(
|
|
arg=FunctionType(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
FundamentalSpecifier(
|
|
name="int"
|
|
)
|
|
]
|
|
)
|
|
),
|
|
parameters=[],
|
|
)
|
|
)
|
|
]
|
|
),
|
|
),
|
|
]
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
|
parameters=[],
|
|
has_trailing_return=True,
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_inline_volatile_fn() -> None:
|
|
content = """
|
|
inline int Standard_Atomic_Increment (volatile int* theValue);
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
|
),
|
|
name=PQName(
|
|
segments=[NameSpecifier(name="Standard_Atomic_Increment")]
|
|
),
|
|
parameters=[
|
|
Parameter(
|
|
type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
),
|
|
volatile=True,
|
|
)
|
|
),
|
|
name="theValue",
|
|
)
|
|
],
|
|
inline=True,
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_method_w_reference() -> None:
|
|
content = """
|
|
struct StreamBuffer
|
|
{
|
|
StreamBuffer &operator<<(std::ostream &(*fn)(std::ostream &))
|
|
{
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
classes=[
|
|
ClassScope(
|
|
class_decl=ClassDecl(
|
|
typename=PQName(
|
|
segments=[NameSpecifier(name="StreamBuffer")],
|
|
classkey="struct",
|
|
)
|
|
),
|
|
methods=[
|
|
Method(
|
|
return_type=Reference(
|
|
ref_to=Type(
|
|
typename=PQName(
|
|
segments=[NameSpecifier(name="StreamBuffer")]
|
|
)
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="operator<<")]),
|
|
parameters=[
|
|
Parameter(
|
|
type=Pointer(
|
|
ptr_to=FunctionType(
|
|
return_type=Reference(
|
|
ref_to=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(name="std"),
|
|
NameSpecifier(
|
|
name="ostream"
|
|
),
|
|
]
|
|
)
|
|
)
|
|
),
|
|
parameters=[
|
|
Parameter(
|
|
type=Reference(
|
|
ref_to=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
NameSpecifier(
|
|
name="std"
|
|
),
|
|
NameSpecifier(
|
|
name="ostream"
|
|
),
|
|
]
|
|
)
|
|
)
|
|
)
|
|
)
|
|
],
|
|
)
|
|
),
|
|
name="fn",
|
|
)
|
|
],
|
|
has_body=True,
|
|
access="public",
|
|
operator="<<",
|
|
)
|
|
],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_w_mvreference() -> None:
|
|
content = """
|
|
void fn1(int && (*)(int));
|
|
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn1")]),
|
|
parameters=[
|
|
Parameter(
|
|
type=Pointer(
|
|
ptr_to=FunctionType(
|
|
return_type=MoveReference(
|
|
moveref_to=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
FundamentalSpecifier(name="int")
|
|
]
|
|
)
|
|
)
|
|
),
|
|
parameters=[
|
|
Parameter(
|
|
type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
FundamentalSpecifier(name="int")
|
|
]
|
|
)
|
|
)
|
|
)
|
|
],
|
|
)
|
|
)
|
|
)
|
|
],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_msvc_conventions() -> None:
|
|
content = """
|
|
void __cdecl fn();
|
|
typedef const char* (__stdcall *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="fn")]),
|
|
parameters=[],
|
|
msvc_convention="__cdecl",
|
|
)
|
|
],
|
|
typedefs=[
|
|
Typedef(
|
|
type=Pointer(
|
|
ptr_to=FunctionType(
|
|
return_type=Pointer(
|
|
ptr_to=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="char")]
|
|
),
|
|
const=True,
|
|
)
|
|
),
|
|
parameters=[
|
|
Parameter(
|
|
type=Type(
|
|
typename=PQName(
|
|
segments=[NameSpecifier(name="HDC")]
|
|
)
|
|
),
|
|
name="theDeviceContext",
|
|
)
|
|
],
|
|
msvc_convention="__stdcall",
|
|
)
|
|
),
|
|
name="wglGetExtensionsStringARB_t",
|
|
)
|
|
],
|
|
)
|
|
)
|
|
|
|
|
|
def test_throw_empty() -> None:
|
|
content = """
|
|
void foo() throw() { throw std::runtime_error("foo"); }
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="foo")]),
|
|
parameters=[],
|
|
has_body=True,
|
|
throw=Value(tokens=[]),
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_throw_dynamic() -> None:
|
|
content = """
|
|
void foo() throw(std::exception) { throw std::runtime_error("foo"); }
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="foo")]),
|
|
parameters=[],
|
|
has_body=True,
|
|
throw=Value(
|
|
tokens=[
|
|
Token(value="std"),
|
|
Token(value="::"),
|
|
Token(value="exception"),
|
|
]
|
|
),
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_noexcept_empty() -> None:
|
|
content = """
|
|
void foo() noexcept;
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="foo")]),
|
|
parameters=[],
|
|
noexcept=Value(tokens=[]),
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_noexcept_contents() -> None:
|
|
content = """
|
|
void foo() noexcept(false);
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="foo")]),
|
|
parameters=[],
|
|
noexcept=Value(tokens=[Token(value="false")]),
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_auto_decltype_return() -> None:
|
|
content = """
|
|
class C {
|
|
public:
|
|
int x;
|
|
auto GetSelected() -> decltype(x);
|
|
};
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
classes=[
|
|
ClassScope(
|
|
class_decl=ClassDecl(
|
|
typename=PQName(
|
|
segments=[NameSpecifier(name="C")], classkey="class"
|
|
)
|
|
),
|
|
fields=[
|
|
Field(
|
|
access="public",
|
|
type=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="int")]
|
|
)
|
|
),
|
|
name="x",
|
|
)
|
|
],
|
|
methods=[
|
|
Method(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[
|
|
DecltypeSpecifier(tokens=[Token(value="x")])
|
|
]
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="GetSelected")]),
|
|
parameters=[],
|
|
has_trailing_return=True,
|
|
access="public",
|
|
)
|
|
],
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_fn_trailing_return_with_body() -> None:
|
|
content = """
|
|
auto test() -> void
|
|
{
|
|
}
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
functions=[
|
|
Function(
|
|
return_type=Type(
|
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="test")]),
|
|
parameters=[],
|
|
has_body=True,
|
|
has_trailing_return=True,
|
|
)
|
|
]
|
|
)
|
|
)
|
|
|
|
|
|
def test_method_trailing_return_with_body() -> None:
|
|
content = """
|
|
struct X {
|
|
auto test() -> void
|
|
{
|
|
}
|
|
};
|
|
"""
|
|
data = parse_string(content, cleandoc=True)
|
|
|
|
assert data == ParsedData(
|
|
namespace=NamespaceScope(
|
|
classes=[
|
|
ClassScope(
|
|
class_decl=ClassDecl(
|
|
typename=PQName(
|
|
segments=[NameSpecifier(name="X")], classkey="struct"
|
|
)
|
|
),
|
|
methods=[
|
|
Method(
|
|
return_type=Type(
|
|
typename=PQName(
|
|
segments=[FundamentalSpecifier(name="void")]
|
|
)
|
|
),
|
|
name=PQName(segments=[NameSpecifier(name="test")]),
|
|
parameters=[],
|
|
has_body=True,
|
|
has_trailing_return=True,
|
|
access="public",
|
|
)
|
|
],
|
|
)
|
|
]
|
|
)
|
|
)
|