// semmle-extractor-options: -std=c++17 template void check_type(const char* expected); template void check_func(TFunc func, const char* expected); template void check_var(TVar var, const char* expected); struct S { enum NestedEnum { Blah, Bluh }; int i; float f; }; struct T { bool b; }; enum E { One, Two, Three }; void checks() { // Primitive types check_type("char"); check_type("unsigned char"); check_type("signed char"); check_type("short"); check_type("short"); check_type("unsigned short"); check_type("int"); check_type("int"); check_type("unsigned int"); check_type("long"); check_type("long"); check_type("unsigned long"); check_type("long long"); check_type("long long"); check_type("unsigned long long"); check_type("float"); check_type("double"); check_type("long double"); check_type("bool"); check_type("wchar_t"); check_type("char16_t"); check_type("char32_t"); check_type("void"); check_type("decltype(nullptr)"); check_type("char const"); check_type("short volatile"); check_type("int const volatile"); check_type("long const volatile"); // Pointers and references check_type("int*"); check_type("int**"); check_type("int&"); check_type("int&&"); check_type("int**&&"); // Qualifiers check_type("int const*"); check_type("int* const"); check_type("float const volatile* volatile"); check_type("char32_t volatile&&"); // Arrays check_type("int[]"); check_type("int[10]"); check_type("int[5][10]"); check_type("int[][7]"); // Functions check_type("int(float)"); check_type("int(*)(float, double)"); check_type("int(**)(float, double, ...)"); check_type("int(&)(float, double)"); check_type("int(*&)(float, double)"); check_type int>("int(float, double)"); check_type auto (*)(double) -> int>("int(*(*)(float))(double)"); check_type("int(*(*)(float))(double)"); check_type("int(*(float))(double)"); // Pointers-to-member check_type("int S::*"); check_type("int const S::* volatile"); check_type("float*(*)(double)"); check_type("float* (S::*)(double)"); check_type("float* (S::*)(double) const"); typedef int (S::* PMF_S)(float) volatile; typedef PMF_S(T::* PMF_T)(double) const; check_type("int (S::* (T::*)(double) const)(float) volatile"); check_type("int (S::* (T::*)(double) const)(float) volatile"); check_type("int S::* T::*"); check_type("bool const (S::* volatile)[10]"); check_type("bool const S::* volatile[10]"); // Complicated stuff typedef int Int10[10]; check_type("int(*)[10]"); check_type("int(*)[10]"); typedef int FuncA(float, double); typedef FuncA* FuncB(wchar_t); check_type("int(*(*&)(wchar_t))(float, double)"); check_type("int(*(*&)(wchar_t))(float, double)"); typedef const int CI; typedef volatile CI VCI; typedef volatile int VI; typedef const VI CVI; check_type("int const"); check_type("int const volatile"); check_type("int volatile"); check_type("int const volatile"); check_type("int const"); typedef int AI[10]; typedef const AI CAI; check_type("int[10]"); check_type("int const[10]"); check_type("int const[10]"); check_type("E"); check_type("S::NestedEnum"); } int globalVariable; int globalFunc(float x); int overloadedGlobalFunc(float x); float overloadedGlobalFunc(int x); template T variableTemplate; auto vt = &variableTemplate; namespace Outer { namespace Inner { template int globalFunctionTemplate(T t, U u) { class LocalClass { public: T x; void MemberFuncOfLocalClass() { } }; check_func(&LocalClass::MemberFuncOfLocalClass, "void (int Outer::Inner::globalFunctionTemplate(long, double))::LocalClass::MemberFuncOfLocalClass()"); { class LocalClassInBlock { public: U x; void MemberFuncOfLocalClassInBlock() { } }; check_func(&LocalClassInBlock::MemberFuncOfLocalClassInBlock, "void (int Outer::Inner::globalFunctionTemplate(long, double))::LocalClassInBlock::MemberFuncOfLocalClassInBlock()"); } auto l = [](int x) { struct LocalClassInLambda { void MemberFuncOfLocalClassInLambda() { } }; check_func(&LocalClassInLambda::MemberFuncOfLocalClassInLambda, "void (int (int Outer::Inner::globalFunctionTemplate(long, double))::(lambda [] type at line ?, col. ?)::operator()(int) const)::LocalClassInLambda::MemberFuncOfLocalClassInLambda()"); return x; }; return 0; } } } struct GlobalStruct { int f; static float s[156]; GlobalStruct MemberFunc(wchar_t); const GlobalStruct ConstMemberFunc(char) const; GlobalStruct volatile VolatileMemberFunc(char16_t) volatile; volatile GlobalStruct const ConstVolatileMemberFunc(char32_t) volatile const; static bool& StaticMemberFunc(float); }; template struct ClassTemplate { T f; U g; }; void sym_checks() { check_func(globalFunc, "int globalFunc(float)"); check_func(static_cast(overloadedGlobalFunc), "int overloadedGlobalFunc(float)"); check_func(static_cast(overloadedGlobalFunc), "float overloadedGlobalFunc(int)"); check_func(Outer::Inner::globalFunctionTemplate, "int Outer::Inner::globalFunctionTemplate(long, double)"); check_func(GlobalStruct::StaticMemberFunc, "bool& GlobalStruct::StaticMemberFunc(float)"); check_func(&GlobalStruct::MemberFunc, "GlobalStruct GlobalStruct::MemberFunc(wchar_t)"); check_func(&GlobalStruct::ConstMemberFunc, "GlobalStruct const GlobalStruct::ConstMemberFunc(char) const"); check_func(&GlobalStruct::VolatileMemberFunc, "GlobalStruct volatile GlobalStruct::VolatileMemberFunc(char16_t) volatile"); check_func(&GlobalStruct::ConstVolatileMemberFunc, "GlobalStruct const volatile GlobalStruct::ConstVolatileMemberFunc(char32_t) const volatile"); check_var(globalVariable, "int globalVariable"); check_var(variableTemplate, "long double variableTemplate"); check_var(&GlobalStruct::f, "int GlobalStruct::f"); check_var(GlobalStruct::s, "float GlobalStruct::s[156]"); check_var(&ClassTemplate::g, "signed char ClassTemplate::g"); }