blob: 858e89e6428ccbd4adf8d7df69e92e71ca54df77 [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2011-2014 Google, Inc. All rights reserved.
* **********************************************************/
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Google, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#include "configure.h"
#if defined(UNIX) || defined(_MSC_VER)
# include "tools.h"
#else /* cygwin/mingw */
# include <windows.h>
# include <stdio.h>
# include <assert.h>
# define print(...) fprintf(stderr, __VA_ARGS__)
/* we want PE exports so dr_get_proc_addr finds them */
# define EXPORT __declspec(dllexport)
# define NOINLINE __declspec(noinline)
#endif
#include <new> /* for std::nothrow_t */
#ifdef UNIX
# include "dlfcn.h"
#endif
static int (*dll_export)(int);
/* Put the class in an anonymous namespace to get the same effect as C static.
* We want to make sure we can find the debug info even if it's not in
* .debug_pubnames. __attribute__((visibility("hidden"))) isn't the same as C
* static, it just means it's not exported when linked into a DSO.
*/
namespace {
class Foo {
public:
int NOINLINE Bar(int a);
};
class HasFields {
public:
int x;
bool y;
short z;
char a[4];
};
}
int NOINLINE
Foo::Bar(int a) {
return dll_export(a+1);
}
extern "C" EXPORT int
exe_export(int a)
{
Foo f;
return f.Bar(a+1);
}
NOINLINE int
exe_public(int a)
{
return exe_export(a+1);
}
static NOINLINE int
exe_static(int a)
{
return exe_public(a+1);
}
int overloaded(char *a) { return 1; }
int overloaded(wchar_t *a) { return 2; }
int overloaded(int *a) { return 4; }
int overloaded(void *a) { return 8; }
int overloaded(Foo *a) { return 16; }
int overloaded(HasFields *a) { return 32; }
/* test an empty struct */
int overloaded(std::nothrow_t *a) { return 64; }
/* no arg so not really an overload, but we need to test no-arg func */
int overloaded(void) { return 128; }
template<typename T> T *
templated_func(T *t)
{
return t;
}
/* test some nesting */
namespace name_outer {
namespace name_middle {
namespace name_inner {
template<typename X>
class sample_class {
public:
template<typename Y>
class nested_class {
public:
template<typename T > T *
templated_func(T *t)
{
return t;
}
union {
int zz;
};
};
};
}
}
}
void
test_templates(void)
{
int x = 4;
int *y = templated_func<int>(&x);
print("got back %d\n", *y);
char c = 'x';
name_outer::name_middle::name_inner::sample_class<char>::nested_class<int> sc;
y = sc.templated_func<int>(&x);
print("got back %d\n", *y);
}
int
main(int argc, char **argv)
{
int num_calls;
#ifdef WINDOWS
HMODULE lib;
#else
void *lib;
#endif
/* Get appdll path. */
if (argc < 2) {
print("need to pass in appdll path.\n");
return 1;
}
#ifdef WINDOWS
lib = LoadLibrary(argv[1]);
if (lib == NULL) {
print("error loading library %s\n", argv[1]);
} else {
dll_export = (int (*)(int))GetProcAddress(lib, "dll_export");
}
#else
lib = dlopen(argv[1], RTLD_LAZY|RTLD_LOCAL);
dll_export = (int (*)(int))dlsym(lib, "dll_export");
#endif
assert(dll_export != NULL);
/* Call a function which calls other functions so we can test looking up the
* PCs from the stack trace.
*/
num_calls = exe_static(0);
print("overloaded: %d\n", overloaded((char *)NULL));
print("overloaded: %d\n", overloaded((wchar_t*)NULL));
print("overloaded: %d\n", overloaded((int *)NULL));
#ifdef WINDOWS
FreeLibrary(lib);
#else
dlclose(lib);
#endif
print("app num_calls: %d\n", num_calls);
test_templates();
return 0;
}