Differentiate String Literal from Char Array - c++

I want to write some function that takes a string literal - and only a string literal:
template <size_t N>
void foo(const char (&str)[N]);
Unfortunately, that is too expansive and will match any array of char - whether or not it's a true string literal. While it's impossible to tell the difference between these at compile-time - without having to resort to requiring the caller to wrap the literal/array - at run-time, the two arrays will be in entirely different places in memory:
foo("Hello"); // at 0x400f81
const char msg[] = {'1', '2', '3'};
foo(msg); // at 0x7fff3552767f
Is there a way to know where in memory the string data could live so that I could at least assert that the function takes a string literal only? (Using gcc 4.7.3, but really a solution for any compiler would be great).

You seem to assume that a necessary trait of a "true string literal"
is that the compiler bakes it into the static storage of the executable.
This is not actually true. The C and C++ standards guarantee us that
a string literal shall have static storage duration, so it must exist for the
life of the program, but if a compiler can arrange this without placing
the literal in static storage, it is free to do so, and some compilers sometimes
do.
However, it's clear that the property you want to test, for a given string
literal, is whether it is in fact in static storage. And since it need not
be in static storage, as far as the language standards guarantee, there
can't be any solution of your problem founded solely on portable C/C++.
Whether a given string literal is in fact in static storage is the question
of whether the address of the string literal lies within one of the
address ranges that get assigned to linkage sections that qualify as
static storage, in the nomenclature of your particular toolchain, when
your program is built by that toolchain.
So the solution I suggest is that you enable your program to know the
address ranges of those of its own linkage sections that qualify as
static storage, and then it can test whether a given string literal
is in static storage by obvious code.
Here is an illustration of this solution for a toy C++ project, prog
built with the GNU/Linux x86_64 toolchain (C++98 or better will do, and the
approach is only slightly more fiddly for C). In this setting, we link in ELF
format, and the linkage sections we will deem static storage are .bss (0-initialized static data), .rodata
(read-only static static) and .data (read/write static data).
Here are our source files:
section_bounds.h
#ifndef SECTION_BOUNDS_H
#define SECTION_BOUNDS_H
// Export delimiting values for our `.bss`, `.rodata` and `.data` sections
extern unsigned long const section_bss_start;
extern unsigned long const section_bss_size;
extern unsigned long const section_bss_end;
extern unsigned long const section_rodata_start;
extern unsigned long const section_rodata_size;
extern unsigned long const section_rodata_end;
extern unsigned long const section_data_start;
extern unsigned long const section_data_size;
extern unsigned long const section_data_end;
#endif
section_bounds.cpp
// Assign either placeholder or pre-defined values to
// the section delimiting globals.
#ifndef BSS_START
#define BSS_START 0x0
#endif
#ifndef BSS_SIZE
#define BSS_SIZE 0xffff
#endif
#ifndef RODATA_START
#define RODATA_START 0x0
#endif
#ifndef RODATA_SIZE
#define RODATA_SIZE 0xffff
#endif
#ifndef DATA_START
#define DATA_START 0x0
#endif
#ifndef DATA_SIZE
#define DATA_SIZE 0xffff
#endif
extern unsigned long const
section_bss_start = BSS_START;
extern unsigned long const section_bss_size = BSS_SIZE;
extern unsigned long const
section_bss_end = section_bss_start + section_bss_size;
extern unsigned long const
section_rodata_start = RODATA_START;
extern unsigned long const
section_rodata_size = RODATA_SIZE;
extern unsigned long const
section_rodata_end = section_rodata_start + section_rodata_size;
extern unsigned long const
section_data_start = DATA_START;
extern unsigned long const
section_data_size = DATA_SIZE;
extern unsigned long const
section_data_end = section_data_start + section_data_size;
cstr_storage_triage.h
#ifndef CSTR_STORAGE_TRIAGE_H
#define CSTR_STORAGE_TRIAGE_H
// Classify the storage type addressed by `s` and print it on `cout`
extern void cstr_storage_triage(const char *s);
#endif
cstr_storage_triage.cpp
#include "cstr_storage_triage.h"
#include "section_bounds.h"
#include <iostream>
using namespace std;
void cstr_storage_triage(const char *s)
{
unsigned long addr = (unsigned long)s;
cout << "When s = " << (void*)s << " -> \"" << s << '\"' << endl;
if (addr >= section_bss_start && addr < section_bss_end) {
cout << "then s is in static 0-initialized data\n";
} else if (addr >= section_rodata_start && addr < section_rodata_end) {
cout << "then s is in static read-only data\n";
} else if (addr >= section_data_start && addr < section_data_end){
cout << "then s is in static read/write data\n";
} else {
cout << "then s is on the stack/heap\n";
}
}
main.cpp
// Demonstrate storage classification of various arrays of char
#include "cstr_storage_triage.h"
static char in_bss[1];
static char const * in_rodata = "In static read-only data";
static char in_rwdata[] = "In static read/write data";
int main()
{
char on_stack[] = "On stack";
cstr_storage_triage(in_bss);
cstr_storage_triage(in_rodata);
cstr_storage_triage(in_rwdata);
cstr_storage_triage(on_stack);
cstr_storage_triage("Where am I?");
return 0;
}
Here is our makefile:
.PHONY: all clean
SRCS = main.cpp cstr_storage_triage.cpp section_bounds.cpp
OBJS = $(SRCS:.cpp=.o)
TARG = prog
MAP_FILE = $(TARG).map
ifdef AGAIN
BSS_BOUNDS := $(shell grep -m 1 '^\.bss ' $(MAP_FILE))
BSS_START := $(word 2,$(BSS_BOUNDS))
BSS_SIZE := $(word 3,$(BSS_BOUNDS))
RODATA_BOUNDS := $(shell grep -m 1 '^\.rodata ' $(MAP_FILE))
RODATA_START := $(word 2,$(RODATA_BOUNDS))
RODATA_SIZE := $(word 3,$(RODATA_BOUNDS))
DATA_BOUNDS := $(shell grep -m 1 '^\.data ' $(MAP_FILE))
DATA_START := $(word 2,$(DATA_BOUNDS))
DATA_SIZE := $(word 3,$(DATA_BOUNDS))
CPPFLAGS += \
-DBSS_START=$(BSS_START) \
-DBSS_SIZE=$(BSS_SIZE) \
-DRODATA_START=$(RODATA_START) \
-DRODATA_SIZE=$(RODATA_SIZE) \
-DDATA_START=$(DATA_START) \
-DDATA_SIZE=$(DATA_SIZE)
endif
all: $(TARG)
clean:
rm -f $(OBJS) $(MAP_FILE) $(TARG)
ifndef AGAIN
$(MAP_FILE): $(OBJS)
g++ -o $(TARG) $(CXXFLAGS) -Wl,-Map=$# $(OBJS) $(LDLIBS)
touch section_bounds.cpp
$(TARG): $(MAP_FILE)
$(MAKE) AGAIN=1
else
$(TARG): $(OBJS)
g++ -o $# $(CXXFLAGS) $(OBJS) $(LDLIBS)
endif
Here is what make looks like:
$ make
g++ -c -o main.o main.cpp
g++ -c -o cstr_storage_triage.o cstr_storage_triage.cpp
g++ -c -o section_bounds.o section_bounds.cpp
g++ -o prog -Wl,-Map=prog.map main.o cstr_storage_triage.o section_bounds.o
touch section_bounds.cpp
make AGAIN=1
make[1]: Entering directory `/home/imk/develop/SO/string_lit_only'
g++ -DBSS_START=0x00000000006020c0 -DBSS_SIZE=0x118 -DRODATA_START=0x0000000000400bf0
-DRODATA_SIZE=0x120 -DDATA_START=0x0000000000602070 -DDATA_SIZE=0x3a
-c -o section_bounds.o section_bounds.cpp
g++ -o prog main.o cstr_storage_triage.o section_bounds.o
And lastly, what prog does:
$ ./prog
When s = 0x6021d1 -> ""
then s is in static 0-initialized data
When s = 0x400bf4 -> "In static read-only data"
then s is in static read-only data
When s = 0x602090 -> "In static read/write data"
then s is in static read/write data
When s = 0x7fffa1b053a0 -> "On stack"
then s is on the stack/heap
When s = 0x400c0d -> "Where am I?"
then s is in static read-only data
If it's obvious how this works, you need read no further.
The program will compile and link even before we know the addresses and
sizes of its static storage sections. It would need too, wouldn't it!? In
that case, the global section_* variables that ought to hold these values
all get built with place-holder values.
When make is run, the recipes:
$(TARG): $(MAP_FILE)
$(MAKE) AGAIN=1
and
$(MAP_FILE): $(OBJS)
g++ -o $(TARG) $(CXXFLAGS) -Wl,-Map=$# $(OBJS) $(LDLIBS)
touch section_bounds.cpp
are operative, because AGAIN is undefined. They tell make that in order
to build prog it must first build the linker map file of prog, as per
the second recipe, and then re-timestamp section_bounds.cpp. After that,
make is to call itself again, with AGAIN defined = 1.
Excecuting the makefile again, with AGAIN defined, make now finds that it
must compute all the variables:
BSS_BOUNDS
BSS_START
BSS_SIZE
RODATA_BOUNDS
RODATA_START
RODATA_SIZE
DATA_BOUNDS
DATA_START
DATA_SIZE
For each static storage section S, it computes S_BOUNDS by grepping
the linker map file for the line that reports the address and size of S.
From that line, it assigns the 2nd word ( = the section address) to S_START,
and the 3rd word ( = the size of the section) to S_SIZE. All the section
delimiting values are then appended, via -D options to the CPPFLAGS
that will automatically be passed to compilations.
Because AGAIN is defined, the operative recipe for $(TARG) is now the customary:
$(TARG): $(OBJS)
g++ -o $# $(CXXFLAGS) $(OBJS) $(LDLIBS)
But we touched section_bounds.cpp in the parent make; so it has to be
recompiled, and therefore prog has to be relinked. This time, when
section_bounds.cpp is compiled, all the section-delimiting macros:
BSS_START
BSS_SIZE
RODATA_START
RODATA_SIZE
DATA_START
DATA_SIZE
will have pre-defined values and will not assume their place-holder values.
And those predefined values will be correct because the second linkage
adds no symbols to the linkage and removes none, and does not alter the
size or storage class of any symbol. It just assigns different values to
symbols that were present in the first linkage. Consequently, the
addresses and sizes of the static storage sections will be unaltered and are now known to your program.

Depending on what exactly you want, this may or may not work for you:
#include <cstdlib>
template <size_t N>
void foo(const char (&str)[N]) {}
template <char> struct check_literal {};
#define foo(arg) foo((check_literal<arg[0]>(),arg))
int main()
{
// This compiles
foo("abc");
// This does not
static const char abc[] = "abc";
foo(abc);
}
This works with g++ and clang++ in -std=c++11 mode only.

You can use user-defined literals, that by definitions can only be applied to literals:
#include <iostream>
struct literal_wrapper
{
const char* const ptr;
private:
constexpr literal_wrapper(const char* p) : ptr(p) {}
friend constexpr literal_wrapper operator "" _lw(const char* p, std::size_t);
};
constexpr literal_wrapper operator "" _lw(const char* p, std::size_t){ return literal_wrapper(p); }
literal_wrapper f()
{
std::cout << "f()" << std::endl;
return "test"_lw;
}
void foo(const literal_wrapper& lw)
{
std::cout << "foo:" << lw.ptr << " " << static_cast<const void*>(lw.ptr) << std::endl;
}
int main()
{
auto x1 = f(), x2 = f(), x3 = f();
const void* p1 = x1.ptr;
const void* p2 = x2.ptr;
const void* p3 = x3.ptr;
std::cout << x1.ptr << " " << p1 << " " << p2 << " " << p3 << std::endl;
foo(x1);
foo(x2);
foo("test"_lw);
foo("test2"_lw);
}

Related

constexpr function which is shared in multiple modules

I noticed a strange behavior when I was working with a constexpr function.
I reduced the code to a simplified example.
Two functions are called from two different translation units (module A and B).
#include <iostream>
int mod_a();
int mod_b();
int main()
{
std::cout << "mod_a(): " << mod_a() << "\n";
std::cout << "mod_b(): " << mod_b() << "\n";
std::cout << std::endl;
return 0;
}
The modules look similar. This is mod_a.cpp:
constexpr int X = 3;
constexpr int Y = 4;
#include "common.h"
int mod_a()
{
return get_product();
}
Only some internal constants differ. This is mod_b.cpp:
constexpr int X = 6;
constexpr int Y = 7;
#include "common.h"
int mod_b()
{
return get_product();
}
Both modules use a common constexpr function which is defined in "common.h":
/* static */ constexpr int get_product()
{
return X * Y;
}
I was very astonished that both functions return 12. Due to the #include directive (which should only be some source code inclusion), I supposed that there is no interaction between both modules.
When I defined get_product also to be static, the behavior was as expected:
mod_a() returned 12,
mod_b() returned 42.
I also looked Jason Turner's episode 312 of C++ Weekly: Stop Using 'constexpr' (And Use This Instead!) at https://www.youtube.com/watch?v=4pKtPWcl1Go.
The advice to use generally static constexpr is a good hint.
But I still wonder if the behavior which I noticed without the static keyword is well defined. Or is it UB? Or is it a compiler bug?
Instead of the constexpr function I also tried a C-style macro #define get_product() (X*Y) which showed me also the expected results (12 and 42).
Take care
michaeL
This program ill-formed: X and Y have internal linkage since they are const variables at namespace scope. This means that both definitions of constexpr int get_product() (which is implicitly inline) violate the one definition rule:
There can be more than one definition in a program of each of the following: [...], inline function, [...], as long as all the following is true:
[...]
name lookup from within each definition finds the same entities (after overload-resolution), except that
constants with internal or no linkage may refer to different objects as long as they are not odr-used and have the same values in every definition
And obviously these constants have different values.
What's happening is both mod_a and mod_b are calling get_product at runtime. get_product is implicitly inline, so one of the definitions is chosen and the other is discarded. What gcc seems to do is take the first definition found:
$ g++ mod_a.cpp mod_b.cpp main.cpp && ./a.out
mod_a(): 12
mod_b(): 12
$ g++ mod_b.cpp mod_a.cpp main.cpp && ./a.out
mod_a(): 42
mod_b(): 42
$ g++ -c mod_a.cpp
$ g++ -c mod_b.cpp
$ g++ mod_a.o mod_b.o main.cpp && ./a.out
mod_a(): 12
mod_b(): 12
$ g++ mod_b.o mod_a.o main.cpp && ./a.out
mod_a(): 42
mod_b(): 42
It's as if get_product isn't constexpr, since it is getting called at runtime.
But if you were to enable optimisations (or force get_product() to be called at compile time, like with constexpr int result = get_product(); return result;), the results are as you would "expect":
$ g++ -O1 mod_a.cpp mod_b.cpp main.cpp && ./a.out
mod_a(): 12
mod_b(): 42
(Though this is still UB, and the correct fix is to make the functions static)
This code violates the One Definition Rule (language lawyers please correct me if I'm wrong).
If I compile the code separately, I get the behavior that you expect:
g++ -O1 -c main.cpp
g++ -O1 -c mod_a.cpp
g++ -O1 -c mod_b.cpp
g++ *.o
./a.out
> mod_a(): 12
> mod_b(): 42
If I compile all at once or activate link-time optimization, the UB becomes apparent.
g++ -O1 *.cpp
./a.out
> mod_a(): 12
> mod_b(): 12
How to fix this
You are on the right track with declaring them static. More C++-esce would be an anonymous namespace. You should also declare the constants static or put them in a namespace, not just the function.
mod_a.cpp:
namespace {
constexpr int X = 3;
constexpr int Y = 4;
}
#include "common.h"
int mod_a()
{
return get_product();
}
common.h:
namespace {
constexpr int get_product()
{
return X * Y;
}
} /* namespace anonymous */
Even better, in my opinion: Include the common.h within an opened namespace. That makes the connection between the declarations more apparent and would allow you to have multiple public get_products, one per namespace. Something like this:
mod_a.cpp:
namespace {
constexpr int X = 3;
constexpr int Y = 4;
#include "common.h"
} /* namespace anonymous */
int mod_a()
{
return get_product();
}

undefined reference to : what's wrong?

Im' trying to port a home made software from AIX to "Red Hat Enterprise Linux 7.8"
I'm facing "undefined reference to" errors at link time and, for now, I can't find where I screwed up.
The goal is to generate an executable from 2 homemade shared librairies (msi and atmi), some object previously compiled (MsiServices.o) and a C program (pingsrv.c).
Below is the command :
gcc -DWall -o bin/pingsrv -DUNIX -I. -g -DUNIX -D_THREAD_SAFE -D_LARGEFILE64_SOURCE -I/home/vgi/git/msi-tools/ping/server/target/msi/include/yaml-cpp -I/home/vgi/git/msi-tools/ping/server/target/msi/include/apr-1 -I/home/vgi/git/msi-tools/ping/server/target/msi/include/activemq-cpp-3.9.4 -I/home/vgi/git/msi-tools/ping/server/target/msi/include /tmp/MsiServices.o ./pingsrv.c -L/home/vgi/git/msi-tools/ping/server/target/msi/lib -lmsi -lactivemq-cpp -llog4cxx -latmi -lapr-1 -laprutil-1 -lexpat -lstdc++ -lyaml-cpp
Errors appears a link time:
/home/vgi/git/msi-tools/ping/server/target/msi/lib/libatmi.so: undefined reference to `Msi_tpreturn'
/home/vgi/git/msi-tools/ping/server/target/msi/lib/libatmi.so: undefined reference to `Msi_tpcall'
/home/vgi/git/msi-tools/ping/server/target/msi/lib/libmsi.so: undefined reference to `msi::service::optarg'
/home/vgi/git/msi-tools/ping/server/target/msi/lib/libatmi.so: undefined reference to `Msi_userlog'
Library atmi is written in C and is able to call some C++ instance methods by using wrappers:
...
typedef struct MsiScheduler MsiScheduler ;
extern void Msi_tpreturn(MsiScheduler *,int, long , char *, long, long);
extern void Msi_userlog(MsiScheduler *,char*) ;
extern int Msi_tpcall(MsiScheduler *,char *svc, char *idata, long ilen, char **odata, long *olen, long flags) ;
...
extern void tpreturn(int rval, long rcode, char * data, long len, long flags)
{
assert(vg_Consumer != NULL) ;
Msi_tpreturn(vg_Consumer,rval,rcode,data,len,flags) ;
}
Wrappers called by this library are defined in another library called msi. Wrappers are defined in a C++ source file (MsiScheduler.cpp):
void Msi_tpreturn(MsiScheduler * c,int ret,long code,char *data,long len,long flags)
{
TypedBuffer* buffer = NULL ;
if (data != NULL)
{
buffer = TypedBuffer::createBuffer(getType(data),data,len) ;
}
MsiReply * reply = MsiReply::createReply(ret,code,buffer) ;
c->tpreturn(reply) ;
if (data != NULL)
{
freebuf(data) ;
}
delete reply ;
}
int Msi_tpcall(MsiScheduler * c,char *svc, char *idata, long ilen, char **odata, long *olen, long flags)
{
...
}
void Msi_userlog(MsiScheduler *c ,char* str)
{
c->userlog(str) ;
}
header file (MsiScheduler.h) contains this fragment :
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__STDC__) || defined(__cplusplus)
extern void Msi_tpreturn(MsiScheduler *,int, long , char *, long, long);
extern void Msi_userlog(MsiScheduler *,char*) ;
extern int Msi_tpcall(MsiScheduler *,char *svc, char *idata, long ilen, char **odata, long *olen, long flags) ;
#else
extern void Msi_tpreturn();
extern void Msi_userlog() ;
extern int Msi_tpcall() ;
#endif
#ifdef __cplusplus
}
#endif
Librairies are constructed like that:
g++ -g -fPIC -Wall -I/home/vgi/git/msi/msi-service/target/ext/include/apr-1 -I/home/vgi/git/msi/msi-service/target/ext/include/activemq-cpp-3.9.4 -I/home/vgi/git/msi/msi-service/target/ext/include/yaml-cpp -I/home/vgi/git/msi/msi-service/target/ext/include -I/home/vgi/git/msi/msi-service/target/ext/include -I../lib/inc -I./ -o MsiScheduler.o -c MsiScheduler.cpp
...
g++ -shared MsiUtil.o MsiConfig.o MsiInstrumentation.o MsiMetric.o MsiService.o MsiExceptions.o MsiCharsetConverter.o MsiTypes.o MsiMessage.o MsiMessageUtil.o MsiScheduler.o MsiServer.o -o libmsi.so
...
gcc -g -fPIC -Wall -I/home/vgi/git/msi/msi-service/target/ext/include/apr-1 -I/home/vgi/git/msi/msi-service/target/ext/include/activemq-cpp-3.9.4 -I/home/vgi/git/msi/msi-service/target/ext/include/yaml-cpp -I/home/vgi/git/msi/msi-service/target/ext/include -I/home/vgi/git/msi/msi-service/target/ext/include -I../lib/inc -I./ -o atmi.o -c atmi.c
gcc -shared atmi.o memmngt.o -o libatmi.so
FYI, everything compile and link well on AIX OS (with xlc,xlC commands).
I also tried to change librairies order for linking command, without success.
I guess there is something specific to linux/gcc but I haven't found it yet.
libmsi.so:0000000000034f20 T _Z10Msi_tpcallPN3msi7service12MsiSchedulerEPcS3_lPS3_Pll
libmsi.so:0000000000035138 T _Z11Msi_userlogPN3msi7service12MsiSchedulerEPc
libmsi.so:0000000000034e55 T _Z12Msi_tpreturnPN3msi7service12MsiSchedulerEilPcll
libatmi.so: U Msi_tpcall
libatmi.so: U Msi_tpreturn
libatmi.so: U Msi_userlog
In your nm output, the T's mean that the symbol on the right is defined in libmsi.so, and the U's mean that the symbol on the right is needed by libatmi.so. But obviously, the names of these symbols don't match up. The names in libmsi.so have the C++ mangling which helps keep overloaded functions separate.
This means the extern "C" did not apply to the function definitions when compiling MsiScheduler.cpp. Make sure it includes MsiScheduler.h, and that part of the header is not skipped by any #if. If that's not the issue, double check that the function parameter types are exactly the same in the MsiScheduler.h declarations and MsiScheduler.cpp definitions, though they seem to be.
When you're compiling pingsrv.c you try to link msi with -l. Have you put libmsi.so in the library path so that -l can find it?

Why is extern required for const int but not for const char*

I'm confused about why I need extern or not for int vs char* in the definition in my extern.cpp file. I have the following test program:
// extern.cpp
extern const int my_int = 1;
const char* my_str = "FOO";
// main.cpp
#include <iostream>
extern const int my_int;
extern const char* my_str;
int main() {
std::cout << my_int;
std::cout << my_str;
return 0;
}
If I remove the extern from extern const int my_int = 1; then I get undefined reference to 'my_int'. If I add extern to const char* my_str = "FOO"; then I get a warning 'my_str' initialized and declared 'extern'. Why do I need extern on my_int but adding it to my_str generates a warning?
This is C++17 on gcc 10.1.0. The specific commands are:
/usr/bin/g++-10 -g -std=gnu++17 -o main.cpp.o -c main.cpp
/usr/bin/g++-10 -g -std=gnu++17 -o extern.cpp.o -c extern.cpp
/usr/bin/g++-10 -g main.cpp.o extern.cpp.o -o TestExtern
This is caused by different linkage of my_int and my_str variables.
my_int is a const-qualified variable in namespace scope, which means it has internal linkage by default. In other words, its visibility is limited to the current translation unit, unless you mark it extern. Additionally, internal linkage constants must have an initializer.
my_str, on the other hand, is not const-qualified. Don't be confused by the const qualifier in the pointer type, as that qualifier is part of the pointed type. The pointer itself is mutable, and you could assign it a different value in run time. Since this is a non-const variable in namespace scope, it has external linkage, and as such refers to a single pointer object in the scope of the whole program.

Error: Invalid use of void

I'm compiling C++ source (main.cpp) with a C header (hps_linux.h). The code in hps_linux.h is:
#ifndef HPS_LINUX_H_
#define HPS_LINUX_H_
#include <stdbool.h>
#include <stdint.h>
#include "socal/hps.h"
int fd_dev_mem = 0;
void *h2f_lw_axi_master = NULL;
size_t h2f_lw_axi_master_span = ALT_LWFPGASLVS_UB_ADDR -ALT_LWFPGASLVS_LB_ADDR + 1;
size_t h2f_lw_axi_master_ofst = ALT_LWFPGASLVS_OFST;
#endif
hps_linux.h includes hps.h, that has the next defines:
#define ALT_LWFPGASLVS_OFST 0xff200000
#define ALT_LWFPGASLVS_ADDR ALT_CAST(void *, (ALT_CAST(char *, ALT_HPS_ADDR) + ALT_LWFPGASLVS_OFST))
#define ALT_LWFPGASLVS_LB_ADDR ALT_LWFPGASLVS_ADDR
#define ALT_LWFPGASLVS_UB_ADDR ALT_CAST(void *, ((ALT_CAST(char *, ALT_LWFPGASLVS_ADDR) + 0x200000) - 1))
My main.cpp includes hps_linux.h . I'm compiling like this:
gcc -Wall -std=gnu99 hps_linux.c -o hps_linux.o
g++ -Wall -std=c++0x main.cpp -o main
And it throws the next error:
hps_linux.h: error: invalid use of 'void'
In line:
size_t h2f_lw_axi_master_span = ALT_LWFPGASLVS_UB_ADDR -ALT_LWFPGASLVS_LB_ADDR + 1;
When I compile it with a main written in C (main.c), it works.
Looking at the source code here, we have:
#ifdef __ASSEMBLY__
# define ALT_CAST(type, ptr) ptr // <-- not (ptr)???
#else
# define ALT_CAST(type, ptr) ((type) (ptr))
#endif /* __ASSEMBLY__ */
Now, we have:
size_t h2f_lw_axi_master_span = ALT_LWFPGASLVS_UB_ADDR - ALT_LWFPGASLVS_LB_ADDR + 1;
Partially expanding the macros, we have:
size_t h2f_lw_axi_master_span = ALT_CAST(void *, ALT_CAST(char *, ...)) - ALT_CAST(void *, ALT_CAST(char *, ...)) + 1;
Now, if __ASSEMBLY__ is set, this line is:
size_t h2f_lw_axi_master_span = ... - ... + 1;
Both ... expressions are integer, so this is OK. However, if __ASSEMBLY__ is not set, this line is:
size_t h2f_lw_axi_master_span = (void *) (...) - (void *) (...) + 1;
Subtracting two void pointers is not defined, so the compiler gives up.
Therefore, you need to ensure __ASSEMBLY__ is defined; one way would be:
g++ -Wall -D__ASSEMBLY__ -std=c++0x main.cpp -o main
However, this might cause problems as you should be relying on the earlier header files to set it correctly.
Update: A quick search of the git archive does not show __ASSEMBLY__ being set, and given the name it suggests it should be a compiler built-in...

Replacing symbol from object file at compile time. For example swapping out main

Here's the use case:
I have a .cpp file which has functions implemented in it. For sake of example say it has the following:
[main.cpp]
#include <iostream>
int foo(int);
int foo(int a) {
return a * a;
}
int main() {
for (int i = 0; i < 5; i += 1) {
std::cout << foo(i) << std::endl;
}
return 0;
}
I want to perform some amount of automated testing on the function foo in this file but would need to replace out the main() function to do my testing. Preferably I'd like to have a separate file like this that I could link in over top of that one:
[mymain.cpp]
#include <iostream>
#include <cassert>
extern int foo(int);
int main() {
assert(foo(1) == 1);
assert(foo(2) == 4);
assert(foo(0) == 0);
assert(foo(-2) == 4);
return 0;
}
I'd like (if at all possible) to avoid changing the original .cpp file in order to do this -- though this would be my approach if this is not possible:
do a replace for "(\s)main\s*\(" ==> "\1__oldmain\("
compile as usual.
The environment I am targeting is a linux environment with g++.
I hate answering my own question, but here's a solution I ended up finding deep in the man page of g++, I've tested it and it works to what I would want it to...
g++ has the -D flag which allows you to define macros when compiling object files. I know you are thinking "ugh macros" but hear me out... You can use the macro definition to effectively rename a symbol. In my case, I can run the following command to generate an object file of my students code without their main file: g++ -D main=__students_main__ main.cpp -c -o main.nomain.o.
This creates an object file with their int main defined as int __students_main__. Now this isn't necessarily callable directly as they could have defined main as int main(void) or with the various combinations of argc and argv, but it allows me to effectively compile out their function.
The final compile looks like this:
g++ -c -D main=__students_main__ main.cpp -o main.nomain.o
g++ -c mymain.cpp -o mymain.o
g++ main.nomain.o mymain.o -o mymainstudentsfoo.out
For my purposes, I wanted to create a Makefile that would accomplish this automagically (ish) and I feel that is relevant to this discussion so I'll post what I came up with:
HDIR=./ # Not relevant to question, but we have headers in a separate directory
CC=g++
CFLAGS=-I $(HDIR)
NOMAIN=-D main=__student_main__ # The main renaming magic
.SECONDARY: # I forget exactly what this does, I seem to remember it is a hack to prevent deletion of .o files
cpp = $(wildcard *.cpp)
obj = $(patsubst %.cpp,%.o,$(cpp))
objnomain = $(patsubst %.cpp,%.nomain.o,$(cpp))
all: $(obj) $(objnomain)
clean:
rm -f *.o *.out
%.nomain.o: %.cpp
$(CC) $(CFLAGS) $(NOMAIN) -c $^ -o $#
%.o: %.cpp
$(CC) $(CFLAGS) -c $^
You can use the --allow-multiple-definition option of ld*:
[a.c]
#include <stdio.h>
int foo() { return 3; }
int bar() { return 4; }
int main(void)
{
printf("foo: %i\n", foo());
return 0;
}
[b.c]
#include <stdio.h>
int bar();
int main(void)
{
printf("bar: %i\n", bar());
return 0;
}
[shell]
$ gcc -Wall -c a.c
$ gcc -Wall -c b.c
$ gcc -Wl,--allow-multiple-definition a.o b.o -o foobar && foobar
foo: 3
$ gcc -Wl,--allow-multiple-definition b.o a.o -o foobar && foobar
bar: 4
*: At your own risk :)
I support 'djechlin's suggestion.
But if you want something quick and dirty, here's a suggestion:
You can define a macro and wrap your function calls like this,
#ifdef MYTESTING
#define ASSERTEQUAL(fn, parm, ret) \
assert( fn ( parm ) == ret )
#else
#define ASSERTEQUAL(fn, parm, ret) fn ( parm )
#endif
And in your main function use the following call,
ASSERTEQUAL( foo, i, 4);
Use the following compilation flag to enable the customized macro behavior.
-DMYTESTING
Hope this helps!
It is not possible to do this at compile time. You need a link time solution. (Or to make use of the preprocessor.)
In either case, you'd probably want to separate the "regular" and "testing" symbols and selectively include their source files in compilation, or object files in linking.*
Though I'd rather use a unit testing framework or at least NDEBUG for assert()s.
*e.g.:
#ifdef TESTING
#include "main-testing.c"
#else
#include "main.c"
#endif
or
ifdef TESTING
OBJS += main-testing.o
else
OBJS += main.o
endif
Update: I just realized that you're specifically looking for a solution where main-testing.o's main would override main.o's (right?). I'll keep this answer and add another one for the "override" solution.