How Does the Linker Handle Identical Template Instantiations Across Translation Units

How does the linker handle identical template instantiations across translation units?

C++ requires that an inline function definition
be present in a translation unit that references the function. Template member
functions are implicitly inline, but also by default are instantiated with external
linkage. Hence the duplication of definitions that will be visible to the linker when
the same template is instantiated with the same template arguments in different
translation units. How the linker copes with this duplication is your question.

Your C++ compiler is subject to the C++ Standard, but your linker is not subject
to any codified standard as to how it shall link C++: it is a law unto itself,
rooted in computing history and indifferent to the source language of the object
code it links. Your compiler has to work with what a target linker
can and will do so that you can successfully link your programs and see them do
what you expect. So I'll show you how the GCC C++ compiler interworks with
the GNU linker to handle identical template instantiations in different translation units.

This demonstration exploits the fact that while the C++ Standard requires -
by the One Definition Rule
- that the instantiations in different translation units of the same template with
the same template arguments shall have the same definition, the compiler -
of course - cannot enforce any requirement like that on relationships between different
translation units. It has to trust us.

So we'll instantiate the same template with the same parameters in different
translation units, but we'll cheat by injecting a macro-controlled difference into
the implementations in different translation units that will subsequently show
us which definition the linker picks.

If you suspect this cheat invalidates the demonstration, remember: the compiler
cannot know whether the ODR is ever honoured across different translation units,
so it cannot behave differently on that account, and there's no such thing
as "cheating" the linker. Anyhow, the demo will demonstrate that it is valid.

First we have our cheat template header:

thing.hpp

#ifndef THING_HPP
#define THING_HPP
#ifndef ID
#error ID undefined
#endif

template<typename T>
struct thing
{
T id() const {
return T{ID};
}
};

#endif

The value of the macro ID is the tracer value we can inject.

Next a source file:

foo.cpp

#define ID 0xf00
#include "thing.hpp"

unsigned foo()
{
thing<unsigned> t;
return t.id();
}

It defines function foo, in which thing<unsigned> is
instantiated to define t, and t.id() is returned. By being a function with
external linkage that instantiates thing<unsigned>, foo serves the purposes
of:-

  • obliging the compiler to do that instantiating at all
  • exposing the instantiation in linkage so we can then probe what the
    linker does with it.

Another source file:

boo.cpp

#define ID 0xb00
#include "thing.hpp"

unsigned boo()
{
thing<unsigned> t;
return t.id();
}

which is just like foo.cpp except that it defines boo in place of foo and
sets ID = 0xb00.

And lastly a program source:

main.cpp

#include <iostream>

extern unsigned foo();
extern unsigned boo();

int main()
{
std::cout << std::hex
<< '\n' << foo()
<< '\n' << boo()
<< std::endl;
return 0;
}

This program will print, as hex, the return value of foo() - which our cheat should make
= f00 - then the return value of boo() - which our cheat should make = b00.

Now we'll compile foo.cpp, and we'll do it with -save-temps because we want
a look at the assembly:

g++ -c -save-temps foo.cpp

This writes the assembly in foo.s and the portion of interest there is
the definition of thing<unsigned int>::id() const (mangled = _ZNK5thingIjE2idEv):

    .section    .text._ZNK5thingIjE2idEv,"axG",@progbits,_ZNK5thingIjE2idEv,comdat
.align 2
.weak _ZNK5thingIjE2idEv
.type _ZNK5thingIjE2idEv, @function
_ZNK5thingIjE2idEv:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp)
movl $3840, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc

Three of the directives at the top are significant:

.section    .text._ZNK5thingIjE2idEv,"axG",@progbits,_ZNK5thingIjE2idEv,comdat

This one puts the function definition in a linkage section of its own called
.text._ZNK5thingIjE2idEv that will be output, if it's needed, merged into the
.text (i.e. code) section of program in which the object file is linked. A
linkage section like that, i.e. .text.<function_name> is called a function-section.
It's a code section that contains only the definition of function <function_name>.

The directive:

.weak   _ZNK5thingIjE2idEv

is crucial. It classifies thing<unsigned int>::id() const as a weak symbol.
The GNU linker recognises strong symbols and weak symbols. For a strong symbol, the
linker will accept only one definition in the linkage. If there are more, it will give a multiple
-definition error. But for a weak symbol, it will tolerate any number of definitions,
and pick one. If a weakly defined symbol also has (just one) strong definition in the linkage then the
strong definition will be picked. If a symbol has multiple weak definitions and no strong definition,
then the linker can pick any one of the weak definitions, arbitrarily.

The directive:

.type   _ZNK5thingIjE2idEv, @function

classifies thing<unsigned int>::id() as referring to a function - not data.

Then in the body of the definition, the code is assembled at the address
labelled by the weak global symbol _ZNK5thingIjE2idEv, the same one locally
labelled .LFB2. The code returns 3840 ( = 0xf00).

Next we'll compile boo.cpp the same way:

g++ -c -save-temps boo.cpp

and look again at how thing<unsigned int>::id() is defined in boo.s

    .section    .text._ZNK5thingIjE2idEv,"axG",@progbits,_ZNK5thingIjE2idEv,comdat
.align 2
.weak _ZNK5thingIjE2idEv
.type _ZNK5thingIjE2idEv, @function
_ZNK5thingIjE2idEv:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp)
movl $2816, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc

It's identical, except for our cheat: this definition returns 2816 ( = 0xb00).

While we're here, let's note something that might or might not go without saying:
Once we're in assembly (or object code), classes have evaporated. Here,
we're down to: -

  • data
  • code
  • symbols, which can label data or label code.

So nothing here specifically represents the instantiation of thing<T> for
T = unsigned. All that's left of thing<unsigned> in this instance is
the definition of _ZNK5thingIjE2idEv a.k.a thing<unsigned int>::id() const.

So now we know what the compiler does about instantiating thing<unsigned>
in a given translation unit. If it is obliged to instantiate a thing<unsigned>
member function, then it assembles the definition of the instantiated member
function at a weakly global symbol that identifies the member function, and it
puts this definition into its own function-section.

Now let's see what the linker does.

First we'll compile the main source file.

g++ -c main.cpp

Then link all the object files, requesting a diagnostic trace on _ZNK5thingIjE2idEv,
and a linkage map file:

g++ -o prog main.o foo.o boo.o -Wl,--trace-symbol='_ZNK5thingIjE2idEv',-M=prog.map
foo.o: definition of _ZNK5thingIjE2idEv
boo.o: reference to _ZNK5thingIjE2idEv

So the linker tells us that the program gets the definition of _ZNK5thingIjE2idEv from
foo.o and calls it in boo.o.

Running the program shows it's telling the truth:

./prog

f00
f00

Both foo() and boo() are returning the value of thing<unsigned>().id()
as instantiated in foo.cpp.

What has become of the other definition of thing<unsigned int>::id() const
in boo.o? The map file shows us:

prog.map

...
Discarded input sections
...
...
.text._ZNK5thingIjE2idEv
0x0000000000000000 0xf boo.o
...
...

The linker chucked away the function-section in boo.o that
contained the other definition.

Let's now link prog again, but this time with foo.o and boo.o in the
reverse order:

$ g++ -o prog main.o boo.o foo.o -Wl,--trace-symbol='_ZNK5thingIjE2idEv',-M=prog.map
boo.o: definition of _ZNK5thingIjE2idEv
foo.o: reference to _ZNK5thingIjE2idEv

This time, the program gets the definition of _ZNK5thingIjE2idEv from boo.o and
calls it in foo.o. The program confirms that:

$ ./prog

b00
b00

And the map file shows:

...
Discarded input sections
...
...
.text._ZNK5thingIjE2idEv
0x0000000000000000 0xf foo.o
...
...

that the linker chucked away the function-section .text._ZNK5thingIjE2idEv
from foo.o.

That completes the picture.

The compiler emits, in each translation unit, a weak definition of
each instantiated template member in its own function section. The linker
then just picks the first of those weak definitions that it encounters
in the linkage sequence when it needs to resolve a reference to the weak
symbol. Because each of the weak symbols addresses a definition, any
one one of them - in particular, the first one - can be used to resolve all references
to the symbol in the linkage, and the rest of the weak definitions are
expendable. The surplus weak definitions must be ignored, because
the linker can only link one definition of a given symbol. And the surplus
weak definitions can be discarded by the linker, with no collateral
damage to the program, because the compiler placed each one in a linkage section all by itself.

By picking the first weak definition it sees, the linker is effectively
picking at random, because the order in which object files are linked is arbitrary.
But this is fine, as long as we obey the ODR accross multiple translation units,
because it we do, then all of the weak definitions are indeed identical. The usual practice of #include-ing a class template everywhere from a header file (and not macro-injecting any local edits when we do so) is a fairly robust way of obeying the rule.

Addresses of identical function template instantiations across compilation units

This is covered under the one definition rule:

3.2 One definition rule [basic.def.odr]

Paragraph 5:

There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then

There is a whole list of criteria that follow that have to be-adhered to or its undefined behavior. In the above these do hold. Then ...

If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D.

So technically you can have a copy of the function in each translation unit.

It looks like the wording in the last phrase though makes it a requirement that they all behave the same. This means taking the address of any of these objects should result in the same address.

The linker attempts to include all not used functions and template instantiations even with function level linkage

For anyone who comes to this question and looks for a solution to similar problem, this is what I ended with :

Instead of moving the implementation to a translation unit .cpp and instantiating all templates there I put the implementation in an internal header file and removed the templates instantiations from the header . For each template instantiation I made a .cpp file which includes the implementation header plus the underlying type interface and instantiate an instant of the class with this type .

Now each instantiation resides in its own file and the linker won't pull unused instants.

A drawback of this approach is the increased implementation files which are there only to go around this problem.

How does extern template actually generate code?

It is actually quite straightforward. Here is a header file that defines template class foo<T>:

foo.hpp

#ifndef FOO_HPP
#define FOO_HPP

template<typename T>
struct foo
{
T const & get() const {
return _t;
}
void set(T const & t) {
_t = t;
}

private:
T _t;
}

#endif

Here is a source file that explicitly instantiates the definition of class foo<int>:

foo_int.cpp

#include "foo.hpp"

// An explicit instantiation definition
template struct foo<int>;

When we compile foo_int.cpp to foo_int.o, that object file will define all
the symbols that accrue from instantiating foo<int>:

$ g++ -Wall -Wextra -pedantic -c foo_int.cpp

$ nm --defined-only foo_int.o
0000000000000000 W _ZN3fooIiE3setERKi
0000000000000000 W _ZNK3fooIiE3getEv

which with de-mangling is:

$ nm -C --defined-only foo_int.o
0000000000000000 W foo<int>::set(int const&)
0000000000000000 W foo<int>::get() const

(Note that symbols are defined weakly
- W - just as they would be as a result of implicit instantiation. Note too that
the compiler saw no need to generate any definitions at all for any of the implicitly defaulted
special member functions.)

Here is a header file that declares an explicit instantiation of foo<int> such
as we just defined in foo_int.o:

foo_int.hpp

#ifndef FOO_INT_HPP
#define FOO_INT_HPP

#include "foo.hpp"

// An explicit instantiation declaration
extern template struct foo<int>;

#endif

Here is a source file that references the explicit instantiation of foo<int>
that we declared in foo_int.hpp:

make_foo_int.cpp

#include "make_foo_int.hpp"

foo<int> make_foo_int(int i)
{
foo<int> fi;
fi.set(i);
return fi;
}

and the associated header file:

make_foo_int.hpp

#ifndef MAKE_FOO_INT_HPP
#define MAKE_FOO_INT_HPP
#include "foo_int.hpp"

foo<int> make_foo_int(int i = 0);

#endif

Note that make_foo_int.cpp is a translation unit of the sort that puzzles
you. It #includes make_foo_int.hpp, which #includes foo_int.hpp,
which #includes foo.hpp - the template definition. And then it "does stuff" with
foo<int>.

When we compile make_foo_int.cpp to make_foo_int.o, that object file
will only contain undefined references to any symbols that accrue from
the instantiation of foo<int>:

$ g++ -Wall -Wextra -pedantic -c make_foo_int.cpp

$ nm -C --defined-only make_foo_int.o
0000000000000000 T make_foo_int(int)

$ nm -C --undefined-only make_foo_int.o
U _GLOBAL_OFFSET_TABLE_
U __stack_chk_fail
U foo<int>::set(int const&)

Does the compiler simply not generate any code involving Foo<int> when compiling this translation unit?

The compiler generates a call to the undefined external function foo<int>::set(int const&). Here is
the assembly:

make_foo_int.s

    .file   "make_foo_int.cpp"
.text
.globl _Z12make_foo_inti
.type _Z12make_foo_inti, @function
_Z12make_foo_inti:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movl %edi, -20(%rbp)
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
leaq -20(%rbp), %rdx
leaq -12(%rbp), %rax
movq %rdx, %rsi
movq %rax, %rdi
call _ZN3fooIiE3setERKi@PLT
movl -12(%rbp), %eax
movq -8(%rbp), %rcx
xorq %fs:40, %rcx
je .L3
call __stack_chk_fail@PLT
.L3:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size _Z12make_foo_inti, .-_Z12make_foo_inti
.ident "GCC: (Ubuntu 8.2.0-7ubuntu1) 8.2.0"
.section .note.GNU-stack,"",@progbits

int which:

call    _ZN3fooIiE3setERKi@PLT

is the call to foo<int>::set(int const&) through the Procedure Lookup Table,
just as it might generate a call to any undefined external function that is to be
resolved at linktime.

Now here is a source file for a program that calls make_foo_int and also foo<int>::get:

main.cpp

#include "make_foo_int.hpp"
#include <iostream>

int main()
{
std::cout << make_foo_int(42).get() << std::endl;
return 0;
}

If we compile main.cpp, the object file will also contain only undefined references
to symbols that accrue from the instantiation of foo<int>:

$ g++ -Wall -Wextra -pedantic -c main.cpp

$ nm -C --defined-only main.o | grep foo; echo Done
Done

$ nm -C --undefined-only main.o | grep foo; echo Done
U make_foo_int(int)
U foo<int>::get() const
Done

If we attempt to link a program using just main.o and make_foo_int.o:

$ g++ -o prog main.o make_foo_int.o
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x2c): undefined reference to `foo<int>::get() const'
/usr/bin/ld: make_foo_int.o: in function `make_foo_int(int)':
make_foo_int.cpp:(.text+0x29): undefined reference to `foo<int>::set(int const&)'
collect2: error: ld returned 1 exit status

it fails with undefined references to foo<int>::get() and foo<int>::set(int const&).

If we relink with the addition of the necessary foo_int.o and ask the linker to
report the references and definitions of those symbols:

$ g++ -o prog main.o make_foo_int.o foo_int.o -Wl,-trace-symbol=_ZN3fooIiE3setERKi,-trace-symbol=_ZNK3fooIiE3getEv
/usr/bin/ld: main.o: reference to _ZNK3fooIiE3getEv
/usr/bin/ld: make_foo_int.o: reference to _ZN3fooIiE3setERKi
/usr/bin/ld: foo_int.o: definition of _ZNK3fooIiE3getEv
/usr/bin/ld: foo_int.o: definition of _ZN3fooIiE3setERKi

we succeed, and see that the linker finds a reference to foo<int>::get() in main.o,
a reference to foo<int>::set(int const&) in make_foo_int.o and
the definitions of both symbols in foo_int.o. foo<int> was instantiated
only once, in foo_int.o.

Later...

Per your comments, you still don't see how the function make_foo_int(int) can be
compiled without the compiler instantiating foo<int> if only for the purpose
of computing the size that the automatic object foo<int> fi that is defined
in the function will occupy on the stack.

The better to address that, I first need draw out a point that was probably insufficiently
clear before when I noted that the explicit instantiation:

template struct foo<int>;

in foo_int.cpp generates only definitions of the member functions that are defined
by the template
, as shown by:

$ nm -C --defined-only foo_int.o
0000000000000000 W foo<int>::set(int const&)
0000000000000000 W foo<int>::get() const

and does not generate definitions of the implicitly defaulted special members of
the class - constructors, etc.

So, a problem very like yours is: How can the function make_foo_int(int) be compiled without the compiler instantiating at least the default constructor that is
executed by:

foo<int> fi;

? The answer is: it does instantiate that constructor, inline, just as it usually would.
(At least, it will do if the constructor is not a no-op). But it only does so because
we did not define that constructor in the template that we explicitly instantiated
in
foo_int.cpp.

Let's change the template slightly too:

foo.hpp (2)

#ifndef FOO_HPP
#define FOO_HPP

template<typename T>
struct foo
{
T const & get() const {
return _t;
}
void set(T const & t) {
_t = t;
}

private:
T _t = 257; // <- Default initializer
};

#endif

Then recompile make_foo_int.cpp, saving the assembly:

$ g++ -Wall -Wextra -pedantic -c make_foo_int.cpp -save-temps

which now makes it obvious that the default constructor foo<int>()
is inlined, whereas foo<int>::set(T const &) is called externally:

make_foo_int.s (2)

    .file   "make_foo_int.cpp"
.text
.globl _Z12make_foo_inti
.type _Z12make_foo_inti, @function
_Z12make_foo_inti:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movl %edi, -20(%rbp)
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movl $257, -12(%rbp) ; <- Default initializer
leaq -20(%rbp), %rdx
leaq -12(%rbp), %rax
movq %rdx, %rsi
movq %rax, %rdi
call _ZN3fooIiE3setERKi@PLT ; <- External call
movl -12(%rbp), %eax
movq -8(%rbp), %rcx
xorq %fs:40, %rcx
je .L3
call __stack_chk_fail@PLT
.L3:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size _Z12make_foo_inti, .-_Z12make_foo_inti
.ident "GCC: (Ubuntu 8.2.0-7ubuntu1) 8.2.0"
.section .note.GNU-stack,"",@progbits

The compiler is able to inline, as usual, any special member functions of
foo<int> that we have not defined in the template because the template
definition must be available to it whenever it sees:

extern template struct foo<int>;

as we can verify by changing foo_int.hpp to:

foo_int.hpp (2)

#ifndef FOO_INT_HPP
#define FOO_INT_HPP

//#include "foo.hpp" <- Hide the template definition

template <typename T> struct foo;

// An explicit instantiation declaration
extern template struct foo<int>;

#endif

and attempting:

$ g++ -Wall -Wextra -pedantic -c make_foo_int.cpp -save-temps
In file included from make_foo_int.hpp:3,
from make_foo_int.cpp:1:
foo_int.hpp:9:24: error: explicit instantiation of ‘struct foo<int>’ before definition of template
extern template struct foo<int>;
^~~~~~~~

So here it is quite true to say that the compiler, as you surmised, is "at least partially instantiating foo<int>"
in make_foo_int.o. But it only instantiating a part - the default constructor - that
is not provided as an external reference by:

 extern template struct foo<int>;

and that default constructor is not so provided because we did not define it in
template struct foo<T>.

If we do define constructors in the template, say:

foo.hpp (3)

#ifndef FOO_HPP
#define FOO_HPP

template<typename T>
struct foo
{
foo()
: _t{257}{}
foo(foo const & other)
: _t{other._t}{}
T const & get() const {
return _t;
}
void set(T const & t) {
_t = t;
}

private:
T _t;
};

#endif

then we will find them defined in foo_int.o:

$ g++ -Wall -Wextra -pedantic -c foo_int.cpp
$ nm -C foo_int.o
0000000000000000 W foo<int>::set(int const&)
0000000000000000 W foo<int>::foo(foo<int> const&)
0000000000000000 W foo<int>::foo()
0000000000000000 W foo<int>::foo(foo<int> const&)
0000000000000000 W foo<int>::foo()
0000000000000000 n foo<int>::foo(foo<int> const&)
0000000000000000 n foo<int>::foo()
0000000000000000 W foo<int>::get() const

(It looks as if they are multiply defined, but this an illusion and a distraction!1). And if we
recompile make_foo_int.cpp with foo.hpp 3 and our original foo_int.hpp:
and inspect the new assembly:

$ g++ -Wall -Wextra -pedantic -O0 -c make_foo_int.cpp -save-temps
$ mv make_foo_int.s make_foo_int.s.before # Save that for later
$ cat make_foo_int.s.before
.file "make_foo_int.cpp"
.text
.globl _Z12make_foo_inti
.type _Z12make_foo_inti, @function
_Z12make_foo_inti:
.LFB4:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movq %rdi, -24(%rbp)
movl %esi, -28(%rbp)
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movq -24(%rbp), %rax
movq %rax, %rdi
call _ZN3fooIiEC1Ev@PLT ; <- External ctor call
leaq -28(%rbp), %rdx
movq -24(%rbp), %rax
movq %rdx, %rsi
movq %rax, %rdi
call _ZN3fooIiE3setERKi@PLT ; <- External `set` call
nop
movq -24(%rbp), %rax
movq -8(%rbp), %rcx
xorq %fs:40, %rcx
je .L3
call __stack_chk_fail@PLT
.L3:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE4:
.size _Z12make_foo_inti, .-_Z12make_foo_inti
.ident "GCC: (Ubuntu 8.2.0-7ubuntu1) 8.2.0"
.section .note.GNU-stack,"",@progbits

we see now that the default constructor _ZN3fooIiEC1E as well
as the set member function _ZN3fooIiE3setERKi are called externally.

Relinking our original program, it runs:

$ g++ -Wall -Wextra -pedantic -O0 -o prog main.cpp make_foo_int.cpp foo_int.cpp
$ ./prog
42

Which eventually preps us for the question: How can the compiler know the size
of the object foo<int> fi in order to compile the function make_foo_int, without
instantiating foo<int>?

As make_foo_int.s.before makes clear, the compiler does not need to compute the size
of any such object because, in the code that it generates, no such object exists. C++
classes and instances of classes are unknown in assembly and object code. In object
code, there are only functions and objects of fundamental integral or floating point
types whose sizes are all known from the start. A function is executed, with 0 or more arguments; it possibly acts upon objects
of those fundamental types residing in the stack, the heap or static storage, and
it (typically) returns control to the antecedent context. The C++ statement:

foo<int> fi;

in the body of make_foo_int does not literally compile to the placing of the object
fi on the stack. It compiles to the execution of a function that is the default constructor
of foo<int> - possibly inlined, possibly called externally; it doesn't matter - which places
an integer = 257 on its stack and finishes leaving that integer still on the stack for
its caller. The caller, as ever, does not need to know the callee's net consumption of stack.
We could redefine template struct foo<T> in a (rather insane) way that makes foo<int> a 1000
times bigger:

foo.hpp (4)



Related Topics



Leave a reply



Submit