diff dmd/TraitsExp.d @ 72:2e2a5c3f943a

reduced warnings by adding override to the methods think this also normalizes different line endings used all over the place
author Trass3r
date Sat, 28 Aug 2010 16:19:48 +0200
parents 460959608115
children be2ab491772e
line wrap: on
line diff
--- a/dmd/TraitsExp.d	Sat Aug 28 16:14:07 2010 +0200
+++ b/dmd/TraitsExp.d	Sat Aug 28 16:19:48 2010 +0200
@@ -1,454 +1,454 @@
-module dmd.TraitsExp;
-
-import dmd.Expression;
-import dmd.Identifier;
-import dmd.ArrayTypes;
-import dmd.OutBuffer;
-import dmd.Loc;
-import dmd.Scope;
-import dmd.HdrGenState;
-import dmd.TOK;
-import dmd.TY;
-import dmd.STC;
-import dmd.WANT;
-import dmd.Id;
-import dmd.Global;
-import dmd.Lexer;
-import dmd.ArrayLiteralExp;
-import dmd.VarExp;
-import dmd.StringExp;
-import dmd.DotIdExp;
-import dmd.DotVarExp;
-import dmd.IntegerExp;
-import dmd.TupleExp;
-import dmd.Type;
-import dmd.Dsymbol;
-import dmd.DsymbolExp;
-import dmd.ScopeDsymbol;
-import dmd.FuncDeclaration;
-import dmd.ClassDeclaration;
-import dmd.TemplateDeclaration;
-import dmd.TemplateInstance;
-import dmd.TypeClass;
-import dmd.Util;
-import dmd.expression.Util;
-
-import core.stdc.string : strcmp;
-
-/************************************************
- * Delegate to be passed to overloadApply() that looks
- * for virtual functions.
- */
-
-struct Pvirtuals
-{
-	Expression e1;
-	Expressions exps;
-	int fpvirtuals(void* param, FuncDeclaration f)
-	{   Pvirtuals p = *cast(Pvirtuals*)param;
-
-		if (f.isVirtual())
-		{	Expression e;
-
-			if (p.e1.op == TOK.TOKdotvar)
-			{   DotVarExp dve = cast(DotVarExp)p.e1;
-				e = new DotVarExp(Loc(0), dve.e1, f);
-			}
-			else
-				e = new DsymbolExp(Loc(0), f);
-			p.exps.push(cast(void*)e);
-		}
-		return 0;
-	}
-}
-
-
-
-class TraitsExp : Expression
-{
-	Identifier ident;
-
-	Objects args;
-
-	this(Loc loc, Identifier ident, Objects args)
-	{
-		super(loc, TOK.TOKtraits, this.sizeof);
-		this.ident = ident;
-		this.args = args;
-	}
-
-	Expression syntaxCopy()
-	{
-		return new TraitsExp(loc, ident, TemplateInstance.arraySyntaxCopy(args));
-	}
-
-	Expression semantic(Scope sc)
-	{
-		version (LOGSEMANTIC) {
-			printf("TraitsExp.semantic() %s\n", toChars());
-		}
-		if (ident != Id.compiles && ident != Id.isSame)
-			TemplateInstance.semanticTiargs(loc, sc, args, 1);
-		size_t dim = args ? args.dim : 0;
-		Object o;
-		FuncDeclaration f;
-
-		string ISTYPE(string cond)
-		{
-			return `
-				for (size_t i = 0; i < dim; i++)
-				{   Type t = getType(cast(Object)args.data[i]);
-					if (!t)
-						goto Lfalse;
-					if (!(`~cond~`))
-						goto Lfalse;
-				}
-			if (!dim)
-				goto Lfalse;
-			goto Ltrue;
-			`;
-		}
-
-		string ISDSYMBOL(string cond)
-		{
-			return `for (size_t i = 0; i < dim; i++)
-			{   Dsymbol s = getDsymbol(cast(Object)args.data[i]);
-				if (!s)
-					goto Lfalse;
-				if (!(`~cond~`))
-					goto Lfalse;
-			}
-			if (!dim)
-				goto Lfalse;
-			goto Ltrue;`;
-		}
-
-		if (ident == Id.isArithmetic)
-		{
-			mixin(ISTYPE(`t.isintegral() || t.isfloating()`));
-		}
-		else if (ident == Id.isFloating)
-		{
-			mixin(ISTYPE(q{t.isfloating()}));
-		}
-		else if (ident == Id.isIntegral)
-		{
-			mixin(ISTYPE(q{t.isintegral()}));
-		}
-		else if (ident == Id.isScalar)
-		{
-			mixin(ISTYPE(q{t.isscalar()}));
-		}
-		else if (ident == Id.isUnsigned)
-		{
-			mixin(ISTYPE(q{t.isunsigned()}));
-		}
-		else if (ident == Id.isAssociativeArray)
-		{
-			mixin(ISTYPE(q{t.toBasetype().ty == TY.Taarray}));
-		}
-		else if (ident == Id.isStaticArray)
-		{
-			mixin(ISTYPE(q{t.toBasetype().ty == TY.Tsarray}));
-		}
-		else if (ident == Id.isAbstractClass)
-		{
-			mixin(ISTYPE(q{t.toBasetype().ty == TY.Tclass && (cast(TypeClass)t.toBasetype()).sym.isAbstract()}));
-		}
-		else if (ident == Id.isFinalClass)
-		{
-			mixin(ISTYPE(q{t.toBasetype().ty == TY.Tclass && (cast(TypeClass)t.toBasetype()).sym.storage_class & STC.STCfinal}));
-		}
-		else if (ident == Id.isAbstractFunction)
-		{
-			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isAbstract()}));
-		}
-		else if (ident == Id.isVirtualFunction)
-		{
-			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isVirtual()}));
-		}
-		else if (ident == Id.isFinalFunction)
-		{
-			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isFinal()}));
-		}
-		else if (ident == Id.hasMember ||
-				ident == Id.getMember ||
-				ident == Id.getVirtualFunctions)
-		{
-			if (dim != 2)
-				goto Ldimerror;
-			Object o_ = cast(Object)args.data[0];
-			Expression e = isExpression(cast(Object)args.data[1]);
-			if (!e)
-			{   error("expression expected as second argument of __traits %s", ident.toChars());
-				goto Lfalse;
-			}
-			e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
-			if (e.op != TOKstring)
-			{   error("string expected as second argument of __traits %s instead of %s", ident.toChars(), e.toChars());
-				goto Lfalse;
-			}
-			StringExp se = cast(StringExp)e;
-			se = se.toUTF8(sc);
-			if (se.sz != 1)
-			{   error("string must be chars");
-				goto Lfalse;
-			}
-			Identifier id = Lexer.idPool(fromStringz(cast(char*)se.string_));
-
-			Type t = isType(o_);
-			e = isExpression(o_);
-			Dsymbol s = isDsymbol(o_);
-			if (t)
-				e = typeDotIdExp(loc, t, id);
-			else if (e)
-				e = new DotIdExp(loc, e, id);
-			else if (s)
-			{   e = new DsymbolExp(loc, s);
-				e = new DotIdExp(loc, e, id);
-			}
-			else
-			{   error("invalid first argument");
-				goto Lfalse;
-			}
-
-			if (ident == Id.hasMember)
-			{   /* Take any errors as meaning it wasn't found
-			     */
-				e = e.trySemantic(sc);
-				if (!e)
-				{	if (global.gag)
-					global.errors++;
-					goto Lfalse;
-				}
-				else
-					goto Ltrue;
-			}
-			else if (ident == Id.getMember)
-			{
-				e = e.semantic(sc);
-				return e;
-			}
-			else if (ident == Id.getVirtualFunctions)
-			{
-				uint errors = global.errors;
-				Expression ex = e;
-				e = e.semantic(sc);
-				if (errors < global.errors)
-					error("%s cannot be resolved", ex.toChars());
-
-				/* Create tuple of virtual function overloads of e
-				 */
-				//e.dump(0);
-				Expressions exps = new Expressions();
-				FuncDeclaration f_;
-				if (e.op == TOKvar)
-				{	VarExp ve = cast(VarExp)e;
-					f_ = ve.var.isFuncDeclaration();
-				}
-				else if (e.op == TOKdotvar)
-				{	DotVarExp dve = cast(DotVarExp)e;
-					f_ = dve.var.isFuncDeclaration();
-				}
-				else
-					f_ = null;
-				Pvirtuals p;
-				p.exps = exps;
-				p.e1 = e;
-				overloadApply(f_, &p.fpvirtuals, &p);
-
-				TupleExp tup = new TupleExp(loc, exps);
-				return tup.semantic(sc);
-			}
-			else
-				assert(0);
-		}
-		else if (ident == Id.classInstanceSize)
-		{
-			if (dim != 1)
-				goto Ldimerror;
-			Object o_ = cast(Object)args.data[0];
-			Dsymbol s = getDsymbol(o_);
-			ClassDeclaration cd;
-			if (!s || (cd = s.isClassDeclaration()) is null)
-			{
-				error("first argument is not a class");
-				goto Lfalse;
-			}
-			return new IntegerExp(loc, cd.structsize, Type.tsize_t);
-		}
-		else if (ident == Id.allMembers || ident == Id.derivedMembers)
-		{
-			if (dim != 1)
-				goto Ldimerror;
-			Object o_ = cast(Object)args.data[0];
-			Dsymbol s = getDsymbol(o_);
-			ScopeDsymbol sd;
-			if (!s)
-			{
-				error("argument has no members");
-				goto Lfalse;
-			}
-			if ((sd = s.isScopeDsymbol()) is null)
-			{
-				error("%s %s has no members", s.kind(), s.toChars());
-				goto Lfalse;
-			}
-			Expressions exps = new Expressions;
-			while (1)
-			{   size_t dim_ = ScopeDsymbol.dim(sd.members);
-				for (size_t i = 0; i < dim_; i++)
-				{
-					Dsymbol sm = ScopeDsymbol.getNth(sd.members, i);
-					//printf("\t[%i] %s %s\n", i, sm.kind(), sm.toChars());
-					if (sm.ident)
-					{
-						//printf("\t%s\n", sm.ident.toChars());
-						auto str = sm.ident.toChars();
-
-						/* Skip if already present in exps[]
-						 */
-						for (size_t j = 0; j < exps.dim; j++)
-						{   StringExp se2 = cast(StringExp)exps.data[j];
-							if (strcmp(toStringz(str), cast(char*)se2.string_) == 0)
-								goto Lnext;
-						}
-
-						StringExp se = new StringExp(loc, str);
-						exps.push(cast(void*)se);
-					}
-Lnext:
-					;
-				}
-				ClassDeclaration cd = sd.isClassDeclaration();
-				if (cd && cd.baseClass && ident == Id.allMembers)
-					sd = cd.baseClass;	// do again with base class
-				else
-					break;
-			}
-			Expression e = new ArrayLiteralExp(loc, exps);
-			e = e.semantic(sc);
-			return e;
-		}
-		else if (ident == Id.compiles)
-		{
-			/* Determine if all the objects - types, expressions, or symbols -
-			 * compile without error
-			 */
-			if (!dim)
-				goto Lfalse;
-
-			for (size_t i = 0; i < dim; i++)
-			{   Object o_ = cast(Object)args.data[i];
-				Expression e;
-
-				uint errors = global.errors;
-				global.gag++;
-
-				Type t = isType(o_);
-				if (t)
-				{	Dsymbol s;
-					t.resolve(loc, sc, &e, &t, &s);
-					if (t)
-						t.semantic(loc, sc);
-					else if (e)
-						e.semantic(sc);
-				}
-				else
-				{	e = isExpression(o);
-					if (e)
-						e.semantic(sc);
-				}
-
-				global.gag--;
-				if (errors != global.errors)
-				{   if (global.gag == 0)
-					global.errors = errors;
-					goto Lfalse;
-				}
-			}
-			goto Ltrue;
-		}
-		else if (ident == Id.isSame)
-		{	/* Determine if two symbols are the same
-			 */
-			if (dim != 2)
-				goto Ldimerror;
-			TemplateInstance.semanticTiargs(loc, sc, args, 0);
-			Object o1 = cast(Object)args.data[0];
-			Object o2 = cast(Object)args.data[1];
-			Dsymbol s1 = getDsymbol(o1);
-			Dsymbol s2 = getDsymbol(o2);
-
-			static if (0) {
-				printf("o1: %p\n", o1);
-				printf("o2: %p\n", o2);
-				if (!s1)
-				{   Expression ea = isExpression(o1);
-					if (ea)
-						printf("%s\n", ea.toChars());
-					Type ta = isType(o1);
-					if (ta)
-						printf("%s\n", ta.toChars());
-					goto Lfalse;
-				}
-				else
-					printf("%s %s\n", s1.kind(), s1.toChars());
-			}
-			if (!s1 && !s2)
-			{   Expression ea1 = isExpression(o1);
-				Expression ea2 = isExpression(o2);
-				if (ea1 && ea2 && ea1.equals(ea2))
-					goto Ltrue;
-			}
-
-			if (!s1 || !s2)
-				goto Lfalse;
-
-			s1 = s1.toAlias();
-			s2 = s2.toAlias();
-
-			if (s1 == s2)
-				goto Ltrue;
-			else
-				goto Lfalse;
-		}
-		else
-		{	error("unrecognized trait %s", ident.toChars());
-			goto Lfalse;
-		}
-
-		return null;
-
-Lnottype:
-		error("%s is not a type", o/*.toChars()*/); // BUG: o is Object, no member toChars()
-		goto Lfalse;
-
-Ldimerror:
-		error("wrong number of arguments %d", dim);
-		goto Lfalse;
-
-
-Lfalse:
-		return new IntegerExp(loc, 0, Type.tbool);
-
-Ltrue:
-		return new IntegerExp(loc, 1, Type.tbool);
-	}
-
-	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
-	{
-		buf.writestring("__traits(");
-		buf.writestring(ident.toChars());
-		if (args)
-		{
-			for (int i = 0; i < args.dim; i++)
-			{
-				buf.writeByte(',');
-				Object oarg = cast(Object)args.data[i];
-				ObjectToCBuffer(buf, hgs, oarg);
-			}
-		}
-		buf.writeByte(')');
-	}
-}
+module dmd.TraitsExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.ArrayTypes;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.TY;
+import dmd.STC;
+import dmd.WANT;
+import dmd.Id;
+import dmd.Global;
+import dmd.Lexer;
+import dmd.ArrayLiteralExp;
+import dmd.VarExp;
+import dmd.StringExp;
+import dmd.DotIdExp;
+import dmd.DotVarExp;
+import dmd.IntegerExp;
+import dmd.TupleExp;
+import dmd.Type;
+import dmd.Dsymbol;
+import dmd.DsymbolExp;
+import dmd.ScopeDsymbol;
+import dmd.FuncDeclaration;
+import dmd.ClassDeclaration;
+import dmd.TemplateDeclaration;
+import dmd.TemplateInstance;
+import dmd.TypeClass;
+import dmd.Util;
+import dmd.expression.Util;
+
+import core.stdc.string : strcmp;
+
+/************************************************
+ * Delegate to be passed to overloadApply() that looks
+ * for virtual functions.
+ */
+
+struct Pvirtuals
+{
+	Expression e1;
+	Expressions exps;
+	int fpvirtuals(void* param, FuncDeclaration f)
+	{   Pvirtuals p = *cast(Pvirtuals*)param;
+
+		if (f.isVirtual())
+		{	Expression e;
+
+			if (p.e1.op == TOK.TOKdotvar)
+			{   DotVarExp dve = cast(DotVarExp)p.e1;
+				e = new DotVarExp(Loc(0), dve.e1, f);
+			}
+			else
+				e = new DsymbolExp(Loc(0), f);
+			p.exps.push(cast(void*)e);
+		}
+		return 0;
+	}
+}
+
+
+
+class TraitsExp : Expression
+{
+	Identifier ident;
+
+	Objects args;
+
+	this(Loc loc, Identifier ident, Objects args)
+	{
+		super(loc, TOK.TOKtraits, this.sizeof);
+		this.ident = ident;
+		this.args = args;
+	}
+
+	override Expression syntaxCopy()
+	{
+		return new TraitsExp(loc, ident, TemplateInstance.arraySyntaxCopy(args));
+	}
+
+	override Expression semantic(Scope sc)
+	{
+		version (LOGSEMANTIC) {
+			printf("TraitsExp.semantic() %s\n", toChars());
+		}
+		if (ident != Id.compiles && ident != Id.isSame)
+			TemplateInstance.semanticTiargs(loc, sc, args, 1);
+		size_t dim = args ? args.dim : 0;
+		Object o;
+		FuncDeclaration f;
+
+		string ISTYPE(string cond)
+		{
+			return `
+				for (size_t i = 0; i < dim; i++)
+				{   Type t = getType(cast(Object)args.data[i]);
+					if (!t)
+						goto Lfalse;
+					if (!(`~cond~`))
+						goto Lfalse;
+				}
+			if (!dim)
+				goto Lfalse;
+			goto Ltrue;
+			`;
+		}
+
+		string ISDSYMBOL(string cond)
+		{
+			return `for (size_t i = 0; i < dim; i++)
+			{   Dsymbol s = getDsymbol(cast(Object)args.data[i]);
+				if (!s)
+					goto Lfalse;
+				if (!(`~cond~`))
+					goto Lfalse;
+			}
+			if (!dim)
+				goto Lfalse;
+			goto Ltrue;`;
+		}
+
+		if (ident == Id.isArithmetic)
+		{
+			mixin(ISTYPE(`t.isintegral() || t.isfloating()`));
+		}
+		else if (ident == Id.isFloating)
+		{
+			mixin(ISTYPE(q{t.isfloating()}));
+		}
+		else if (ident == Id.isIntegral)
+		{
+			mixin(ISTYPE(q{t.isintegral()}));
+		}
+		else if (ident == Id.isScalar)
+		{
+			mixin(ISTYPE(q{t.isscalar()}));
+		}
+		else if (ident == Id.isUnsigned)
+		{
+			mixin(ISTYPE(q{t.isunsigned()}));
+		}
+		else if (ident == Id.isAssociativeArray)
+		{
+			mixin(ISTYPE(q{t.toBasetype().ty == TY.Taarray}));
+		}
+		else if (ident == Id.isStaticArray)
+		{
+			mixin(ISTYPE(q{t.toBasetype().ty == TY.Tsarray}));
+		}
+		else if (ident == Id.isAbstractClass)
+		{
+			mixin(ISTYPE(q{t.toBasetype().ty == TY.Tclass && (cast(TypeClass)t.toBasetype()).sym.isAbstract()}));
+		}
+		else if (ident == Id.isFinalClass)
+		{
+			mixin(ISTYPE(q{t.toBasetype().ty == TY.Tclass && (cast(TypeClass)t.toBasetype()).sym.storage_class & STC.STCfinal}));
+		}
+		else if (ident == Id.isAbstractFunction)
+		{
+			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isAbstract()}));
+		}
+		else if (ident == Id.isVirtualFunction)
+		{
+			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isVirtual()}));
+		}
+		else if (ident == Id.isFinalFunction)
+		{
+			mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isFinal()}));
+		}
+		else if (ident == Id.hasMember ||
+				ident == Id.getMember ||
+				ident == Id.getVirtualFunctions)
+		{
+			if (dim != 2)
+				goto Ldimerror;
+			Object o_ = cast(Object)args.data[0];
+			Expression e = isExpression(cast(Object)args.data[1]);
+			if (!e)
+			{   error("expression expected as second argument of __traits %s", ident.toChars());
+				goto Lfalse;
+			}
+			e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			if (e.op != TOKstring)
+			{   error("string expected as second argument of __traits %s instead of %s", ident.toChars(), e.toChars());
+				goto Lfalse;
+			}
+			StringExp se = cast(StringExp)e;
+			se = se.toUTF8(sc);
+			if (se.sz != 1)
+			{   error("string must be chars");
+				goto Lfalse;
+			}
+			Identifier id = Lexer.idPool(fromStringz(cast(char*)se.string_));
+
+			Type t = isType(o_);
+			e = isExpression(o_);
+			Dsymbol s = isDsymbol(o_);
+			if (t)
+				e = typeDotIdExp(loc, t, id);
+			else if (e)
+				e = new DotIdExp(loc, e, id);
+			else if (s)
+			{   e = new DsymbolExp(loc, s);
+				e = new DotIdExp(loc, e, id);
+			}
+			else
+			{   error("invalid first argument");
+				goto Lfalse;
+			}
+
+			if (ident == Id.hasMember)
+			{   /* Take any errors as meaning it wasn't found
+			     */
+				e = e.trySemantic(sc);
+				if (!e)
+				{	if (global.gag)
+					global.errors++;
+					goto Lfalse;
+				}
+				else
+					goto Ltrue;
+			}
+			else if (ident == Id.getMember)
+			{
+				e = e.semantic(sc);
+				return e;
+			}
+			else if (ident == Id.getVirtualFunctions)
+			{
+				uint errors = global.errors;
+				Expression ex = e;
+				e = e.semantic(sc);
+				if (errors < global.errors)
+					error("%s cannot be resolved", ex.toChars());
+
+				/* Create tuple of virtual function overloads of e
+				 */
+				//e.dump(0);
+				Expressions exps = new Expressions();
+				FuncDeclaration f_;
+				if (e.op == TOKvar)
+				{	VarExp ve = cast(VarExp)e;
+					f_ = ve.var.isFuncDeclaration();
+				}
+				else if (e.op == TOKdotvar)
+				{	DotVarExp dve = cast(DotVarExp)e;
+					f_ = dve.var.isFuncDeclaration();
+				}
+				else
+					f_ = null;
+				Pvirtuals p;
+				p.exps = exps;
+				p.e1 = e;
+				overloadApply(f_, &p.fpvirtuals, &p);
+
+				TupleExp tup = new TupleExp(loc, exps);
+				return tup.semantic(sc);
+			}
+			else
+				assert(0);
+		}
+		else if (ident == Id.classInstanceSize)
+		{
+			if (dim != 1)
+				goto Ldimerror;
+			Object o_ = cast(Object)args.data[0];
+			Dsymbol s = getDsymbol(o_);
+			ClassDeclaration cd;
+			if (!s || (cd = s.isClassDeclaration()) is null)
+			{
+				error("first argument is not a class");
+				goto Lfalse;
+			}
+			return new IntegerExp(loc, cd.structsize, Type.tsize_t);
+		}
+		else if (ident == Id.allMembers || ident == Id.derivedMembers)
+		{
+			if (dim != 1)
+				goto Ldimerror;
+			Object o_ = cast(Object)args.data[0];
+			Dsymbol s = getDsymbol(o_);
+			ScopeDsymbol sd;
+			if (!s)
+			{
+				error("argument has no members");
+				goto Lfalse;
+			}
+			if ((sd = s.isScopeDsymbol()) is null)
+			{
+				error("%s %s has no members", s.kind(), s.toChars());
+				goto Lfalse;
+			}
+			Expressions exps = new Expressions;
+			while (1)
+			{   size_t dim_ = ScopeDsymbol.dim(sd.members);
+				for (size_t i = 0; i < dim_; i++)
+				{
+					Dsymbol sm = ScopeDsymbol.getNth(sd.members, i);
+					//printf("\t[%i] %s %s\n", i, sm.kind(), sm.toChars());
+					if (sm.ident)
+					{
+						//printf("\t%s\n", sm.ident.toChars());
+						auto str = sm.ident.toChars();
+
+						/* Skip if already present in exps[]
+						 */
+						for (size_t j = 0; j < exps.dim; j++)
+						{   StringExp se2 = cast(StringExp)exps.data[j];
+							if (strcmp(toStringz(str), cast(char*)se2.string_) == 0)
+								goto Lnext;
+						}
+
+						StringExp se = new StringExp(loc, str);
+						exps.push(cast(void*)se);
+					}
+Lnext:
+					;
+				}
+				ClassDeclaration cd = sd.isClassDeclaration();
+				if (cd && cd.baseClass && ident == Id.allMembers)
+					sd = cd.baseClass;	// do again with base class
+				else
+					break;
+			}
+			Expression e = new ArrayLiteralExp(loc, exps);
+			e = e.semantic(sc);
+			return e;
+		}
+		else if (ident == Id.compiles)
+		{
+			/* Determine if all the objects - types, expressions, or symbols -
+			 * compile without error
+			 */
+			if (!dim)
+				goto Lfalse;
+
+			for (size_t i = 0; i < dim; i++)
+			{   Object o_ = cast(Object)args.data[i];
+				Expression e;
+
+				uint errors = global.errors;
+				global.gag++;
+
+				Type t = isType(o_);
+				if (t)
+				{	Dsymbol s;
+					t.resolve(loc, sc, &e, &t, &s);
+					if (t)
+						t.semantic(loc, sc);
+					else if (e)
+						e.semantic(sc);
+				}
+				else
+				{	e = isExpression(o);
+					if (e)
+						e.semantic(sc);
+				}
+
+				global.gag--;
+				if (errors != global.errors)
+				{   if (global.gag == 0)
+					global.errors = errors;
+					goto Lfalse;
+				}
+			}
+			goto Ltrue;
+		}
+		else if (ident == Id.isSame)
+		{	/* Determine if two symbols are the same
+			 */
+			if (dim != 2)
+				goto Ldimerror;
+			TemplateInstance.semanticTiargs(loc, sc, args, 0);
+			Object o1 = cast(Object)args.data[0];
+			Object o2 = cast(Object)args.data[1];
+			Dsymbol s1 = getDsymbol(o1);
+			Dsymbol s2 = getDsymbol(o2);
+
+			static if (0) {
+				printf("o1: %p\n", o1);
+				printf("o2: %p\n", o2);
+				if (!s1)
+				{   Expression ea = isExpression(o1);
+					if (ea)
+						printf("%s\n", ea.toChars());
+					Type ta = isType(o1);
+					if (ta)
+						printf("%s\n", ta.toChars());
+					goto Lfalse;
+				}
+				else
+					printf("%s %s\n", s1.kind(), s1.toChars());
+			}
+			if (!s1 && !s2)
+			{   Expression ea1 = isExpression(o1);
+				Expression ea2 = isExpression(o2);
+				if (ea1 && ea2 && ea1.equals(ea2))
+					goto Ltrue;
+			}
+
+			if (!s1 || !s2)
+				goto Lfalse;
+
+			s1 = s1.toAlias();
+			s2 = s2.toAlias();
+
+			if (s1 == s2)
+				goto Ltrue;
+			else
+				goto Lfalse;
+		}
+		else
+		{	error("unrecognized trait %s", ident.toChars());
+			goto Lfalse;
+		}
+
+		return null;
+
+Lnottype:
+		error("%s is not a type", o/*.toChars()*/); // BUG: o is Object, no member toChars()
+		goto Lfalse;
+
+Ldimerror:
+		error("wrong number of arguments %d", dim);
+		goto Lfalse;
+
+
+Lfalse:
+		return new IntegerExp(loc, 0, Type.tbool);
+
+Ltrue:
+		return new IntegerExp(loc, 1, Type.tbool);
+	}
+
+	override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("__traits(");
+		buf.writestring(ident.toChars());
+		if (args)
+		{
+			for (int i = 0; i < args.dim; i++)
+			{
+				buf.writeByte(',');
+				Object oarg = cast(Object)args.data[i];
+				ObjectToCBuffer(buf, hgs, oarg);
+			}
+		}
+		buf.writeByte(')');
+	}
+}