mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-16 04:43:14 +01:00
[svn r93] a few fixes, some phobos additions.
some very rough groundwork for moduleinfo and classinfo support
This commit is contained in:
@@ -64,6 +64,8 @@ bool DtoIsTemplateInstance(Dsymbol* s);
|
||||
|
||||
void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type* t);
|
||||
|
||||
void DtoClassInfo(ClassDeclaration* cd);
|
||||
|
||||
// llvm wrappers
|
||||
void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
|
||||
bool DtoCanLoad(llvm::Value* ptr);
|
||||
|
||||
152
gen/toobj.cpp
152
gen/toobj.cpp
@@ -91,6 +91,9 @@ Module::genobjfile()
|
||||
dsym->toObjFile();
|
||||
}
|
||||
|
||||
// generate ModuleInfo
|
||||
genmoduleinfo();
|
||||
|
||||
gTargetData = 0;
|
||||
|
||||
// emit the llvm main function if necessary
|
||||
@@ -139,6 +142,152 @@ Module::genobjfile()
|
||||
|
||||
void Module::genmoduleinfo()
|
||||
{
|
||||
// The layout is:
|
||||
// {
|
||||
// void **vptr;
|
||||
// monitor_t monitor;
|
||||
// char[] name; // class name
|
||||
// ModuleInfo importedModules[];
|
||||
// ClassInfo localClasses[];
|
||||
// uint flags; // initialization state
|
||||
// void *ctor;
|
||||
// void *dtor;
|
||||
// void *unitTest;
|
||||
// }
|
||||
|
||||
if (moduleinfo) {
|
||||
Logger::println("moduleinfo");
|
||||
}
|
||||
if (vmoduleinfo) {
|
||||
Logger::println("vmoduleinfo");
|
||||
}
|
||||
if (needModuleInfo()) {
|
||||
Logger::println("**** ATTENTION: module info is needed but skipped");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Symbol *msym = toSymbol();
|
||||
unsigned offset;
|
||||
unsigned sizeof_ModuleInfo = 12 * PTRSIZE;
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
csym->Sclass = SCglobal;
|
||||
csym->Sfl = FLdata;
|
||||
|
||||
// The layout is:
|
||||
// {
|
||||
// void **vptr;
|
||||
// monitor_t monitor;
|
||||
// char[] name; // class name
|
||||
// ModuleInfo importedModules[];
|
||||
// ClassInfo localClasses[];
|
||||
// uint flags; // initialization state
|
||||
// void *ctor;
|
||||
// void *dtor;
|
||||
// void *unitTest;
|
||||
// }
|
||||
dt_t *dt = NULL;
|
||||
|
||||
if (moduleinfo)
|
||||
dtxoff(&dt, moduleinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ModuleInfo
|
||||
else
|
||||
dtdword(&dt, 0); // BUG: should be an assert()
|
||||
dtdword(&dt, 0); // monitor
|
||||
|
||||
// name[]
|
||||
char *name = toPrettyChars();
|
||||
size_t namelen = strlen(name);
|
||||
dtdword(&dt, namelen);
|
||||
dtabytes(&dt, TYnptr, 0, namelen + 1, name);
|
||||
|
||||
ClassDeclarations aclasses;
|
||||
int i;
|
||||
|
||||
//printf("members->dim = %d\n", members->dim);
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *member;
|
||||
|
||||
member = (Dsymbol *)members->data[i];
|
||||
//printf("\tmember '%s'\n", member->toChars());
|
||||
member->addLocalClass(&aclasses);
|
||||
}
|
||||
|
||||
// importedModules[]
|
||||
int aimports_dim = aimports.dim;
|
||||
for (i = 0; i < aimports.dim; i++)
|
||||
{ Module *m = (Module *)aimports.data[i];
|
||||
if (!m->needModuleInfo())
|
||||
aimports_dim--;
|
||||
}
|
||||
dtdword(&dt, aimports_dim);
|
||||
if (aimports.dim)
|
||||
dtxoff(&dt, csym, sizeof_ModuleInfo, TYnptr);
|
||||
else
|
||||
dtdword(&dt, 0);
|
||||
|
||||
// localClasses[]
|
||||
dtdword(&dt, aclasses.dim);
|
||||
if (aclasses.dim)
|
||||
dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYnptr);
|
||||
else
|
||||
dtdword(&dt, 0);
|
||||
|
||||
if (needmoduleinfo)
|
||||
dtdword(&dt, 0); // flags (4 means MIstandalone)
|
||||
else
|
||||
dtdword(&dt, 4); // flags (4 means MIstandalone)
|
||||
|
||||
if (sctor)
|
||||
dtxoff(&dt, sctor, 0, TYnptr);
|
||||
else
|
||||
dtdword(&dt, 0);
|
||||
|
||||
if (sdtor)
|
||||
dtxoff(&dt, sdtor, 0, TYnptr);
|
||||
else
|
||||
dtdword(&dt, 0);
|
||||
|
||||
if (stest)
|
||||
dtxoff(&dt, stest, 0, TYnptr);
|
||||
else
|
||||
dtdword(&dt, 0);
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
for (i = 0; i < aimports.dim; i++)
|
||||
{
|
||||
Module *m;
|
||||
|
||||
m = (Module *)aimports.data[i];
|
||||
if (m->needModuleInfo())
|
||||
{ Symbol *s = m->toSymbol();
|
||||
s->Sflags |= SFLweak;
|
||||
dtxoff(&dt, s, 0, TYnptr);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < aclasses.dim; i++)
|
||||
{
|
||||
ClassDeclaration *cd;
|
||||
|
||||
cd = (ClassDeclaration *)aclasses.data[i];
|
||||
dtxoff(&dt, cd->toSymbol(), 0, TYnptr);
|
||||
}
|
||||
|
||||
csym->Sdt = dt;
|
||||
#if ELFOBJ
|
||||
// Cannot be CONST because the startup code sets flag bits in it
|
||||
csym->Sseg = DATA;
|
||||
#endif
|
||||
outdata(csym);
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
obj_moduleinfo(msym);
|
||||
*/
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
@@ -553,6 +702,9 @@ void ClassDeclaration::toObjFile()
|
||||
gIR->structs.pop_back();
|
||||
|
||||
llvmInProgress = false;
|
||||
|
||||
// if (ClassDeclaration::classinfo != this)
|
||||
// DtoClassInfo(this);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
|
||||
129
gen/typinf.cpp
129
gen/typinf.cpp
@@ -533,6 +533,7 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
assert(tinfo->ty == Tstruct);
|
||||
TypeStruct *tc = (TypeStruct *)tinfo;
|
||||
StructDeclaration *sd = tc->sym;
|
||||
sd->toObjFile();
|
||||
|
||||
ClassDeclaration* base = Type::typeinfostruct;
|
||||
base->toObjFile();
|
||||
@@ -773,3 +774,131 @@ void TypeInfoTupleDeclaration::toDt(dt_t **pdt)
|
||||
dtxoff(pdt, s, 0, TYnptr); // elements.ptr
|
||||
*/
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
/* ========================================================================= */
|
||||
/* CLASS INFO STUFF */
|
||||
/* ========================================================================= */
|
||||
/* ========================================================================= */
|
||||
|
||||
void DtoClassInfo(ClassDeclaration* cd)
|
||||
{
|
||||
// The layout is:
|
||||
// {
|
||||
// void **vptr;
|
||||
// monitor_t monitor;
|
||||
// byte[] initializer; // static initialization data
|
||||
// char[] name; // class name
|
||||
// void *[] vtbl;
|
||||
// Interface[] interfaces;
|
||||
// ClassInfo *base; // base class
|
||||
// void *destructor;
|
||||
// void *invariant; // class invariant
|
||||
// uint flags;
|
||||
// void *deallocator;
|
||||
// OffsetTypeInfo[] offTi;
|
||||
// void *defaultConstructor;
|
||||
// }
|
||||
|
||||
// holds the list of initializers for llvm
|
||||
std::vector<llvm::Constant*> inits;
|
||||
|
||||
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
|
||||
assert(cinfo);
|
||||
Logger::println("cinfo toObj");
|
||||
cinfo->toObjFile();
|
||||
|
||||
Logger::println("cinfo toObj done");
|
||||
assert(cinfo->type->ty == Tclass);
|
||||
TypeClass* tc = (TypeClass*)cinfo->type;
|
||||
//assert(tc->llvmInit);
|
||||
//assert(cinfo->llvmInitZ);
|
||||
|
||||
cinfo = ClassDeclaration::classinfo;
|
||||
assert(cinfo->llvmInitZ);
|
||||
|
||||
/*
|
||||
llvm::Constant* c;
|
||||
|
||||
// own vtable
|
||||
c = cinfo->llvmInitZ->getOperand(0);
|
||||
assert(c);
|
||||
inits.push_back(c);
|
||||
|
||||
// monitor
|
||||
// TODO no monitors yet
|
||||
|
||||
// initializer
|
||||
c = cinfo->llvmInitZ->getOperand(1);
|
||||
inits.push_back(c);
|
||||
|
||||
// class name
|
||||
// from dmd
|
||||
char *name = cd->ident->toChars();
|
||||
size_t namelen = strlen(name);
|
||||
if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
|
||||
{
|
||||
name = cd->toPrettyChars();
|
||||
namelen = strlen(name);
|
||||
}
|
||||
c = DtoConstString(name);
|
||||
inits.push_back(c);
|
||||
|
||||
// vtbl array
|
||||
c = cinfo->llvmInitZ->getOperand(3);
|
||||
inits.push_back(c);
|
||||
|
||||
// interfaces array
|
||||
c = cinfo->llvmInitZ->getOperand(4);
|
||||
inits.push_back(c);
|
||||
|
||||
// base classinfo
|
||||
c = cinfo->llvmInitZ->getOperand(5);
|
||||
inits.push_back(c);
|
||||
|
||||
// destructor
|
||||
c = cinfo->llvmInitZ->getOperand(5);
|
||||
inits.push_back(c);
|
||||
|
||||
// invariant
|
||||
c = cinfo->llvmInitZ->getOperand(6);
|
||||
inits.push_back(c);
|
||||
|
||||
// flags
|
||||
c = cinfo->llvmInitZ->getOperand(7);
|
||||
inits.push_back(c);
|
||||
|
||||
// allocator
|
||||
c = cinfo->llvmInitZ->getOperand(8);
|
||||
inits.push_back(c);
|
||||
|
||||
// offset typeinfo
|
||||
c = cinfo->llvmInitZ->getOperand(9);
|
||||
inits.push_back(c);
|
||||
|
||||
// default constructor
|
||||
c = cinfo->llvmInitZ->getOperand(10);
|
||||
inits.push_back(c);
|
||||
|
||||
// build the initializer
|
||||
const llvm::StructType* st = llvm::cast<llvm::StructType>(cinfo->llvmInitZ->getType());
|
||||
llvm::Constant* finalinit = llvm::ConstantStruct::get(st, inits);
|
||||
Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
|
||||
|
||||
assert(0);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -32,10 +32,13 @@
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This copy is modified to work with LLVMDC by Tomas Lindquist Olsen 2007
|
||||
*/
|
||||
|
||||
module object;
|
||||
|
||||
//import std.outofmemory;
|
||||
import std.outofmemory;
|
||||
|
||||
/**
|
||||
* An unsigned integral type large enough to span the memory space. Use for
|
||||
@@ -260,6 +263,8 @@ extern (C) void _d_notify_release(Object o)
|
||||
}
|
||||
}
|
||||
|
||||
+/
|
||||
|
||||
/**
|
||||
* Information about an interface.
|
||||
* A pointer to this appears as the first entry in the interface's vtbl[].
|
||||
@@ -272,6 +277,7 @@ struct Interface
|
||||
}
|
||||
|
||||
import std.moduleinit;
|
||||
|
||||
/**
|
||||
* Runtime type information about a class. Can be retrieved for any class type
|
||||
* or instance by using the .classinfo property.
|
||||
@@ -287,7 +293,7 @@ class ClassInfo : Object
|
||||
Interface[] interfaces; /// interfaces this class implements
|
||||
ClassInfo base; /// base class
|
||||
void *destructor;
|
||||
void (*classInvariant)(Object);
|
||||
void function(Object) classInvariant;
|
||||
uint flags;
|
||||
// 1: // IUnknown
|
||||
// 2: // has no possible pointers into GC memory
|
||||
@@ -303,7 +309,7 @@ class ClassInfo : Object
|
||||
*/
|
||||
static ClassInfo find(char[] classname)
|
||||
{
|
||||
foreach (m; ModuleInfo.modules())
|
||||
/+foreach (m; ModuleInfo.modules())
|
||||
{
|
||||
//writefln("module %s, %d", m.name, m.localClasses.length);
|
||||
foreach (c; m.localClasses)
|
||||
@@ -312,7 +318,7 @@ class ClassInfo : Object
|
||||
if (c.name == classname)
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}+/
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -321,7 +327,7 @@ class ClassInfo : Object
|
||||
*/
|
||||
Object create()
|
||||
{
|
||||
if (flags & 8 && !defaultConstructor)
|
||||
/+if (flags & 8 && !defaultConstructor)
|
||||
return null;
|
||||
Object o = _d_newclass(this);
|
||||
if (flags & 8 && defaultConstructor)
|
||||
@@ -329,12 +335,13 @@ class ClassInfo : Object
|
||||
defaultConstructor(o);
|
||||
}
|
||||
return o;
|
||||
+/
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private import std.string;
|
||||
//private import std.string;
|
||||
|
||||
+/
|
||||
|
||||
/**
|
||||
* Array of pairs giving the offset and type information for each
|
||||
|
||||
@@ -4,6 +4,8 @@ import
|
||||
std.array,
|
||||
std.ctype,
|
||||
std.intrinsic,
|
||||
std.moduleinit,
|
||||
std.outofmemory,
|
||||
std.stdint,
|
||||
std.stdio,
|
||||
std.stdarg,
|
||||
|
||||
210
lphobos/std/moduleinit.d
Normal file
210
lphobos/std/moduleinit.d
Normal file
@@ -0,0 +1,210 @@
|
||||
// Modified for LLVMDC
|
||||
|
||||
module std.moduleinit;
|
||||
|
||||
//debug = 1;
|
||||
|
||||
private
|
||||
{
|
||||
import object;
|
||||
import std.c.stdio;
|
||||
import std.c.stdlib;
|
||||
}
|
||||
|
||||
enum
|
||||
{ MIctorstart = 1, // we've started constructing it
|
||||
MIctordone = 2, // finished construction
|
||||
MIstandalone = 4, // module ctor does not depend on other module
|
||||
// ctors being done first
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Information about each module.
|
||||
*/
|
||||
class ModuleInfo
|
||||
{
|
||||
char[] name;
|
||||
ModuleInfo[] importedModules;
|
||||
ClassInfo[] localClasses;
|
||||
|
||||
uint flags; // initialization state
|
||||
|
||||
void function() ctor;
|
||||
void function() dtor;
|
||||
void function() unitTest;
|
||||
|
||||
/******************
|
||||
* Return collection of all modules in the program.
|
||||
*/
|
||||
static ModuleInfo[] modules()
|
||||
{
|
||||
return _moduleinfo_array;
|
||||
}
|
||||
}
|
||||
|
||||
class ModuleCtorError : Exception
|
||||
{
|
||||
this(ModuleInfo m)
|
||||
{
|
||||
super("circular initialization dependency with module " ~ m.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Win32: this gets initialized by minit.asm
|
||||
// linux: this gets initialized in _moduleCtor()
|
||||
extern (C) ModuleInfo[] _moduleinfo_array;
|
||||
|
||||
version (linux)
|
||||
{
|
||||
// This linked list is created by a compiler generated function inserted
|
||||
// into the .ctor list by the compiler.
|
||||
struct ModuleReference
|
||||
{
|
||||
ModuleReference* next;
|
||||
ModuleInfo mod;
|
||||
}
|
||||
|
||||
extern (C) ModuleReference *_Dmodule_ref; // start of linked list
|
||||
}
|
||||
|
||||
ModuleInfo[] _moduleinfo_dtors;
|
||||
uint _moduleinfo_dtors_i;
|
||||
|
||||
// Register termination function pointers
|
||||
extern (C) int _fatexit(void *);
|
||||
|
||||
/*************************************
|
||||
* Initialize the modules.
|
||||
*/
|
||||
|
||||
extern (C) void _moduleCtor()
|
||||
{
|
||||
debug printf("_moduleCtor()\n");
|
||||
version (linux)
|
||||
{
|
||||
int len = 0;
|
||||
ModuleReference *mr;
|
||||
|
||||
for (mr = _Dmodule_ref; mr; mr = mr.next)
|
||||
len++;
|
||||
_moduleinfo_array = new ModuleInfo[len];
|
||||
len = 0;
|
||||
for (mr = _Dmodule_ref; mr; mr = mr.next)
|
||||
{ _moduleinfo_array[len] = mr.mod;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
// Ensure module destructors also get called on program termination
|
||||
//_fatexit(&_STD_moduleDtor);
|
||||
}
|
||||
|
||||
_moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
|
||||
debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
|
||||
_moduleCtor2(_moduleinfo_array, 0);
|
||||
|
||||
version (none)
|
||||
{
|
||||
foreach (m; _moduleinfo_array)
|
||||
{
|
||||
writefln("module %s, %d", m.name, m.localClasses.length);
|
||||
foreach (c; m.localClasses)
|
||||
{
|
||||
writefln("\tclass %s", c.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _moduleCtor2(ModuleInfo[] mi, int skip)
|
||||
{
|
||||
debug printf("_moduleCtor2(): %d modules\n", mi.length);
|
||||
for (uint i = 0; i < mi.length; i++)
|
||||
{
|
||||
ModuleInfo m = mi[i];
|
||||
|
||||
debug printf("\tmodule[%d] = '%p'\n", i, m);
|
||||
if (!m)
|
||||
continue;
|
||||
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
|
||||
if (m.flags & MIctordone)
|
||||
continue;
|
||||
debug printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
|
||||
|
||||
if (m.ctor || m.dtor)
|
||||
{
|
||||
if (m.flags & MIctorstart)
|
||||
{ if (skip || m.flags & MIstandalone)
|
||||
continue;
|
||||
throw new ModuleCtorError(m);
|
||||
}
|
||||
|
||||
m.flags |= MIctorstart;
|
||||
_moduleCtor2(m.importedModules, 0);
|
||||
if (m.ctor)
|
||||
(*m.ctor)();
|
||||
m.flags &= ~MIctorstart;
|
||||
m.flags |= MIctordone;
|
||||
|
||||
// Now that construction is done, register the destructor
|
||||
//printf("\tadding module dtor x%x\n", m);
|
||||
assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
|
||||
_moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
|
||||
}
|
||||
else
|
||||
{
|
||||
m.flags |= MIctordone;
|
||||
_moduleCtor2(m.importedModules, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
* Destruct the modules.
|
||||
*/
|
||||
|
||||
// Starting the name with "_STD" means under linux a pointer to the
|
||||
// function gets put in the .dtors segment.
|
||||
|
||||
extern (C) void _moduleDtor()
|
||||
{
|
||||
debug printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
|
||||
for (uint i = _moduleinfo_dtors_i; i-- != 0;)
|
||||
{
|
||||
ModuleInfo m = _moduleinfo_dtors[i];
|
||||
|
||||
debug printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
|
||||
if (m.dtor)
|
||||
{
|
||||
(*m.dtor)();
|
||||
}
|
||||
}
|
||||
debug printf("_moduleDtor() done\n");
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Run unit tests.
|
||||
*/
|
||||
|
||||
extern (C) void _moduleUnitTests()
|
||||
{
|
||||
debug printf("_moduleUnitTests()\n");
|
||||
for (uint i = 0; i < _moduleinfo_array.length; i++)
|
||||
{
|
||||
ModuleInfo m = _moduleinfo_array[i];
|
||||
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
|
||||
if (m.unitTest)
|
||||
{
|
||||
(*m.unitTest)();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
44
lphobos/std/outofmemory.d
Normal file
44
lphobos/std/outofmemory.d
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdOutOfMemory
|
||||
* Copyright:
|
||||
* Placed into public domain.
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
|
||||
module std.outofmemory;
|
||||
|
||||
/******
|
||||
* This exception is thrown when out of memory errors happen.
|
||||
*/
|
||||
|
||||
class OutOfMemoryException : Exception
|
||||
{
|
||||
static char[] s = "Out of memory";
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
this()
|
||||
{
|
||||
super(s);
|
||||
}
|
||||
|
||||
char[] toString()
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
extern (C) void _d_OutOfMemory()
|
||||
{
|
||||
assert(0);
|
||||
/*throw cast(OutOfMemoryException)
|
||||
cast(void *)
|
||||
OutOfMemoryException.classinfo.init;*/
|
||||
}
|
||||
|
||||
static this()
|
||||
{
|
||||
}
|
||||
5
test/bug52.d
Normal file
5
test/bug52.d
Normal file
@@ -0,0 +1,5 @@
|
||||
module bug52;
|
||||
struct Vec { double x,y,z; }
|
||||
struct Pair(T, U) { T first; U second; }
|
||||
typedef Pair!(double, Vec) Hit;
|
||||
void main() {}
|
||||
11
test/moduleinfo1.d
Normal file
11
test/moduleinfo1.d
Normal file
@@ -0,0 +1,11 @@
|
||||
module moduleinfo1;
|
||||
|
||||
class C
|
||||
{
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
C c;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user