diff --git a/analysis/ifelsesame.d b/analysis/ifelsesame.d new file mode 100644 index 0000000..8d57d11 --- /dev/null +++ b/analysis/ifelsesame.d @@ -0,0 +1,43 @@ +// Copyright Brian Schott (Sir Alaran) 2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +module analysis.ifelsesame; + +import stdx.d.ast; +import stdx.d.lexer; +import analysis.base; + +/** + * Checks for if statements whose "then" block is the same as the "else" block + */ +class IfElseSameCheck : BaseAnalyzer +{ + alias visit = BaseAnalyzer.visit; + + this(string fileName) + { + super(fileName); + } + + override void visit(const IfStatement ifStatement) + { + if (ifStatement.thenStatement == ifStatement.elseStatement) + addErrorMessage(ifStatement.line, ifStatement.column, + "\"Else\" branch is identical to \"Then\" branch."); + ifStatement.accept(this); + } + + override void visit(const AssignExpression assignExpression) + { + const AssignExpression e = cast(const AssignExpression) assignExpression.assignExpression; + if (e !is null && assignExpression.operator == tok!"=" + && e.ternaryExpression == assignExpression.ternaryExpression) + { + addErrorMessage(assignExpression.line, assignExpression.column, + "Left side of assignment operatior is identical to the right side"); + } + assignExpression.accept(this); + } +} diff --git a/analysis/run.d b/analysis/run.d index 74971e1..63b30ee 100644 --- a/analysis/run.d +++ b/analysis/run.d @@ -20,6 +20,7 @@ import analysis.fish; import analysis.numbers; import analysis.objectconst; import analysis.range; +import analysis.ifelsesame; void messageFunction(string fileName, size_t line, size_t column, string message, bool isError) @@ -70,6 +71,7 @@ void analyze(File output, string[] fileNames, bool staticAnalyze = true) checks ~= new NumberStyleCheck(fileName); checks ~= new ObjectConstCheck(fileName); checks ~= new BackwardsRangeCheck(fileName); + checks ~= new IfElseSameCheck(fileName); foreach (check; checks) { diff --git a/stdx/d/ast.d b/stdx/d/ast.d index 636b516..a6d83c5 100644 --- a/stdx/d/ast.d +++ b/stdx/d/ast.d @@ -32,56 +32,56 @@ abstract class ASTVisitor { public: - void visit(const ExpressionNode n) - { - if (cast(AddExpression) n) visit(cast(AddExpression) n); - else if (cast(AndAndExpression) n) visit(cast(AndAndExpression) n); - else if (cast(AndExpression) n) visit(cast(AndExpression) n); - else if (cast(AsmAddExp) n) visit(cast(AsmAddExp) n); - else if (cast(AsmAndExp) n) visit(cast(AsmAndExp) n); - else if (cast(AsmEqualExp) n) visit(cast(AsmEqualExp) n); - else if (cast(AsmLogAndExp) n) visit(cast(AsmLogAndExp) n); - else if (cast(AsmLogOrExp) n) visit(cast(AsmLogOrExp) n); - else if (cast(AsmMulExp) n) visit(cast(AsmMulExp) n); - else if (cast(AsmOrExp) n) visit(cast(AsmOrExp) n); - else if (cast(AsmRelExp) n) visit(cast(AsmRelExp) n); - else if (cast(AsmShiftExp) n) visit(cast(AsmShiftExp) n); - else if (cast(AssertExpression) n) visit(cast(AssertExpression) n); - else if (cast(AssignExpression) n) visit(cast(AssignExpression) n); - else if (cast(CmpExpression) n) visit(cast(CmpExpression) n); - else if (cast(DeleteExpression) n) visit(cast(DeleteExpression) n); - else if (cast(EqualExpression) n) visit(cast(EqualExpression) n); - else if (cast(Expression) n) visit(cast(Expression) n); - else if (cast(FunctionCallExpression) n) visit(cast(FunctionCallExpression) n); - else if (cast(FunctionLiteralExpression) n) visit(cast(FunctionLiteralExpression) n); - else if (cast(IdentityExpression) n) visit(cast(IdentityExpression) n); - else if (cast(ImportExpression) n) visit(cast(ImportExpression) n); - else if (cast(IndexExpression) n) visit(cast(IndexExpression) n); - else if (cast(InExpression) n) visit(cast(InExpression) n); - else if (cast(IsExpression) n) visit(cast(IsExpression) n); - else if (cast(LambdaExpression) n) visit(cast(LambdaExpression) n); - else if (cast(MixinExpression) n) visit(cast(MixinExpression) n); - else if (cast(MulExpression) n) visit(cast(MulExpression) n); - else if (cast(NewAnonClassExpression) n) visit(cast(NewAnonClassExpression) n); - else if (cast(NewExpression) n) visit(cast(NewExpression) n); - else if (cast(OrExpression) n) visit(cast(OrExpression) n); - else if (cast(OrOrExpression) n) visit(cast(OrOrExpression) n); - else if (cast(PostIncDecExpression) n) visit(cast(PostIncDecExpression) n); - else if (cast(PowExpression) n) visit(cast(PowExpression) n); - else if (cast(PragmaExpression) n) visit(cast(PragmaExpression) n); - else if (cast(PreIncDecExpression) n) visit(cast(PreIncDecExpression) n); - else if (cast(PrimaryExpression) n) visit(cast(PrimaryExpression) n); - else if (cast(RelExpression) n) visit(cast(RelExpression) n); - else if (cast(ShiftExpression) n) visit(cast(ShiftExpression) n); - else if (cast(SliceExpression) n) visit(cast(SliceExpression) n); - else if (cast(TemplateMixinExpression) n) visit(cast(TemplateMixinExpression) n); - else if (cast(TernaryExpression) n) visit(cast(TernaryExpression) n); - else if (cast(TraitsExpression) n) visit(cast(TraitsExpression) n); - else if (cast(TypeidExpression) n) visit(cast(TypeidExpression) n); - else if (cast(TypeofExpression) n) visit(cast(TypeofExpression) n); - else if (cast(UnaryExpression) n) visit(cast(UnaryExpression) n); - else if (cast(XorExpression) n) visit(cast(XorExpression) n); - } + void visit(const ExpressionNode n) + { + if (cast(AddExpression) n) visit(cast(AddExpression) n); + else if (cast(AndAndExpression) n) visit(cast(AndAndExpression) n); + else if (cast(AndExpression) n) visit(cast(AndExpression) n); + else if (cast(AsmAddExp) n) visit(cast(AsmAddExp) n); + else if (cast(AsmAndExp) n) visit(cast(AsmAndExp) n); + else if (cast(AsmEqualExp) n) visit(cast(AsmEqualExp) n); + else if (cast(AsmLogAndExp) n) visit(cast(AsmLogAndExp) n); + else if (cast(AsmLogOrExp) n) visit(cast(AsmLogOrExp) n); + else if (cast(AsmMulExp) n) visit(cast(AsmMulExp) n); + else if (cast(AsmOrExp) n) visit(cast(AsmOrExp) n); + else if (cast(AsmRelExp) n) visit(cast(AsmRelExp) n); + else if (cast(AsmShiftExp) n) visit(cast(AsmShiftExp) n); + else if (cast(AssertExpression) n) visit(cast(AssertExpression) n); + else if (cast(AssignExpression) n) visit(cast(AssignExpression) n); + else if (cast(CmpExpression) n) visit(cast(CmpExpression) n); + else if (cast(DeleteExpression) n) visit(cast(DeleteExpression) n); + else if (cast(EqualExpression) n) visit(cast(EqualExpression) n); + else if (cast(Expression) n) visit(cast(Expression) n); + else if (cast(FunctionCallExpression) n) visit(cast(FunctionCallExpression) n); + else if (cast(FunctionLiteralExpression) n) visit(cast(FunctionLiteralExpression) n); + else if (cast(IdentityExpression) n) visit(cast(IdentityExpression) n); + else if (cast(ImportExpression) n) visit(cast(ImportExpression) n); + else if (cast(IndexExpression) n) visit(cast(IndexExpression) n); + else if (cast(InExpression) n) visit(cast(InExpression) n); + else if (cast(IsExpression) n) visit(cast(IsExpression) n); + else if (cast(LambdaExpression) n) visit(cast(LambdaExpression) n); + else if (cast(MixinExpression) n) visit(cast(MixinExpression) n); + else if (cast(MulExpression) n) visit(cast(MulExpression) n); + else if (cast(NewAnonClassExpression) n) visit(cast(NewAnonClassExpression) n); + else if (cast(NewExpression) n) visit(cast(NewExpression) n); + else if (cast(OrExpression) n) visit(cast(OrExpression) n); + else if (cast(OrOrExpression) n) visit(cast(OrOrExpression) n); + else if (cast(PostIncDecExpression) n) visit(cast(PostIncDecExpression) n); + else if (cast(PowExpression) n) visit(cast(PowExpression) n); + else if (cast(PragmaExpression) n) visit(cast(PragmaExpression) n); + else if (cast(PreIncDecExpression) n) visit(cast(PreIncDecExpression) n); + else if (cast(PrimaryExpression) n) visit(cast(PrimaryExpression) n); + else if (cast(RelExpression) n) visit(cast(RelExpression) n); + else if (cast(ShiftExpression) n) visit(cast(ShiftExpression) n); + else if (cast(SliceExpression) n) visit(cast(SliceExpression) n); + else if (cast(TemplateMixinExpression) n) visit(cast(TemplateMixinExpression) n); + else if (cast(TernaryExpression) n) visit(cast(TernaryExpression) n); + else if (cast(TraitsExpression) n) visit(cast(TraitsExpression) n); + else if (cast(TypeidExpression) n) visit(cast(TypeidExpression) n); + else if (cast(TypeofExpression) n) visit(cast(TypeofExpression) n); + else if (cast(UnaryExpression) n) visit(cast(UnaryExpression) n); + else if (cast(XorExpression) n) visit(cast(XorExpression) n); + } /** */ void visit(const AddExpression addExpression) { addExpression.accept(this); } /** */ void visit(const AliasDeclaration aliasDeclaration) { aliasDeclaration.accept(this); } @@ -291,6 +291,14 @@ public: immutable string DEFAULT_ACCEPT = q{override void accept(ASTVisitor visitor) const {}}; +mixin template OpEquals() +{ + override bool opEquals(Object other) const + { + mixin (generateOpEquals!(typeof(this))); + } +} + template visitIfNotNull(fields ...) { static if (fields.length > 1) @@ -311,21 +319,38 @@ template visitIfNotNull(fields ...) } } +template generateOpEquals(T) +{ + template opEqualsPart(p ...) + { + import std.traits; + static if (p.length == 0) + enum opEqualsPart = ""; + else static if (!isSomeFunction!(__traits(getMember, T, p[0])) && p[0] != "line" && p[0] != "column") + enum opEqualsPart = "\n\t&& obj." ~ p[0] ~ " == this." ~ p[0] ~ opEqualsPart!(p[1 .. $]); + else + enum opEqualsPart = opEqualsPart!(p[1 .. $]); + } + enum generateOpEquals = T.stringof ~ " obj = cast(" ~ T.stringof ~ ") other;\n" + ~ "return obj !is null" + ~ opEqualsPart!(__traits(derivedMembers, T)) ~ ";"; +} + abstract class ExpressionNode : ASTNode { public: - override void accept(ASTVisitor visitor) const - { - assert (false); - } + override void accept(ASTVisitor visitor) const + { + assert (false); + } } mixin template BinaryExpressionBody() { ExpressionNode left; ExpressionNode right; - size_t line; - size_t column; + size_t line; + size_t column; } /// @@ -336,6 +361,7 @@ public: { mixin (visitIfNotNull!(left, right)); } + mixin OpEquals; /** */ IdType operator; mixin BinaryExpressionBody; } @@ -348,6 +374,7 @@ public: { mixin (visitIfNotNull!(linkageAttribute, type, name, initializers)); } + mixin OpEquals; /** */ LinkageAttribute linkageAttribute; /** */ Type type; /** */ Token name; @@ -363,7 +390,7 @@ public: { mixin (visitIfNotNull!(name, type)); } - + mixin OpEquals; /** */ Token name; /** */ Type type; } @@ -376,6 +403,7 @@ public: { mixin (visitIfNotNull!(identifier)); } + mixin OpEquals; /** */ Token identifier; } @@ -387,6 +415,7 @@ public: { mixin (visitIfNotNull!(intLiteral)); } + mixin OpEquals; /** */ Token intLiteral; } @@ -398,6 +427,7 @@ public: { mixin (visitIfNotNull!(left, right)); } + mixin OpEquals; mixin BinaryExpressionBody; } @@ -409,6 +439,7 @@ public: { mixin (visitIfNotNull!(left, right)); } + mixin OpEquals; mixin BinaryExpressionBody; } @@ -420,6 +451,7 @@ public: { mixin (visitIfNotNull!(items)); } + mixin OpEquals; /** */ AssignExpression[] items; } @@ -431,6 +463,7 @@ public: { mixin (visitIfNotNull!(argumentList)); } + mixin OpEquals; /** */ ArgumentList argumentList; } @@ -442,6 +475,7 @@ public: { mixin (visitIfNotNull!(arrayMemberInitializations)); } + mixin OpEquals; /** */ ArrayMemberInitialization[] arrayMemberInitializations; } @@ -453,6 +487,7 @@ public: { mixin (visitIfNotNull!(argumentList)); } + mixin OpEquals; /** */ ArgumentList argumentList; } @@ -464,6 +499,7 @@ public: { mixin (visitIfNotNull!(assignExpression, nonVoidInitializer)); } + mixin OpEquals; /** */ AssignExpression assignExpression; /** */ NonVoidInitializer nonVoidInitializer; } @@ -473,6 +509,7 @@ final class AsmAddExp : ExpressionNode { public: mixin (DEFAULT_ACCEPT); + mixin OpEquals; /** */ IdType operator; mixin BinaryExpressionBody; } @@ -482,6 +519,7 @@ final class AsmAndExp : ExpressionNode { public: mixin (DEFAULT_ACCEPT); + mixin OpEquals; mixin BinaryExpressionBody; } @@ -490,6 +528,7 @@ final class AsmBrExp : ASTNode { public: mixin (DEFAULT_ACCEPT); + mixin OpEquals; /** */ AsmBrExp asmBrExp; /** */ AsmEqualExp asmEqualExp; /** */ AsmUnaExp asmUnaExp; @@ -501,6 +540,7 @@ final class AsmEqualExp : ExpressionNode public: mixin (DEFAULT_ACCEPT); mixin BinaryExpressionBody; + mixin OpEquals; /** */ Token operator; } @@ -509,6 +549,7 @@ final class AsmExp : ASTNode { public: mixin (DEFAULT_ACCEPT); + mixin OpEquals; /** */ AsmLogOrExp left; /** */ AsmExp middle; /** */ AsmExp right; @@ -519,6 +560,7 @@ final class AsmInstruction : ASTNode { public: mixin (DEFAULT_ACCEPT); + mixin OpEquals; /** */ Token identifierOrIntegerOrOpcode; /** */ bool hasAlign; /** */ AsmExp asmExp; @@ -531,6 +573,7 @@ final class AsmLogAndExp : ExpressionNode public: mixin (DEFAULT_ACCEPT); mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -539,6 +582,7 @@ final class AsmLogOrExp : ExpressionNode public: mixin (DEFAULT_ACCEPT); mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -548,6 +592,7 @@ public: mixin (DEFAULT_ACCEPT); /** */ IdType operator; mixin BinaryExpressionBody; + mixin OpEquals; } @@ -557,6 +602,7 @@ final class AsmOrExp : ExpressionNode public: mixin (DEFAULT_ACCEPT); mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -567,6 +613,7 @@ public: /** */ IdentifierChain identifierChain; /** */ Register register; /** */ Token token; + mixin OpEquals; } /// @@ -576,6 +623,7 @@ public: mixin (DEFAULT_ACCEPT); mixin BinaryExpressionBody; /** */ Token operator; + mixin OpEquals; } /// @@ -585,6 +633,7 @@ public: mixin (DEFAULT_ACCEPT); mixin BinaryExpressionBody; /** */ Token operator; + mixin OpEquals; } /// @@ -593,6 +642,7 @@ final class AsmStatement : ASTNode public: mixin (DEFAULT_ACCEPT); /** */ AsmInstruction[] asmInstructions; + mixin OpEquals; } /// @@ -602,6 +652,7 @@ public: mixin (DEFAULT_ACCEPT); /** */ Token left; /** */ Token right; + mixin OpEquals; } /// @@ -614,6 +665,7 @@ public: /** */ Token prefix; /** */ AsmPrimaryExp asmPrimaryExp; /** */ AsmUnaExp asmUnaExp; + mixin OpEquals; } /// @@ -622,6 +674,7 @@ final class AsmXorExp : ASTNode public: mixin (DEFAULT_ACCEPT); mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -634,6 +687,7 @@ public: } /** */ AssignExpression assertion; /** */ AssignExpression message; + mixin OpEquals; } /// @@ -647,6 +701,9 @@ public: /** */ ExpressionNode ternaryExpression; /** */ ExpressionNode assignExpression; /** */ IdType operator; + size_t line; + size_t column; + mixin OpEquals; } /// @@ -658,6 +715,7 @@ public: mixin (visitIfNotNull!(keyValuePairs)); } /** */ KeyValuePairs keyValuePairs; + mixin OpEquals; } /// @@ -671,6 +729,7 @@ public: /** */ FunctionCallExpression functionCallExpression; /** */ ArgumentList argumentList; /** */ Token identifier; + mixin OpEquals; } /// @@ -687,6 +746,7 @@ public: /** */ PragmaExpression pragmaExpression; /** */ StorageClass storageClass; /** */ IdType attribute; + mixin OpEquals; } /// @@ -697,6 +757,7 @@ final class AttributeDeclaration : ASTNode mixin (visitIfNotNull!(attribute)); } /** */ Attribute attribute; + mixin OpEquals; } /// @@ -712,6 +773,7 @@ public: } /** */ Token[] identifiers; /** */ Initializer[] initializers; + mixin OpEquals; } /// @@ -734,6 +796,7 @@ public: size_t endLocation; /** */ DeclarationsAndStatements declarationsAndStatements; + mixin OpEquals; } /// @@ -745,6 +808,7 @@ public: mixin (visitIfNotNull!(blockStatement)); } /** */ BlockStatement blockStatement; + mixin OpEquals; } /// @@ -756,6 +820,7 @@ public: mixin (visitIfNotNull!(label)); } /** */ Token label; + mixin OpEquals; } /// @@ -768,6 +833,7 @@ public: } /** */ IdentifierOrTemplateChain identifierOrTemplateChain; /** */ TypeofExpression typeofExpression; + mixin OpEquals; } /// @@ -779,6 +845,7 @@ public: mixin (visitIfNotNull!(items)); } /** */ BaseClass[] items; + mixin OpEquals; } /// @@ -792,6 +859,7 @@ public: /** */ AssignExpression low; /** */ AssignExpression high; /** */ DeclarationsAndStatements declarationsAndStatements; + mixin OpEquals; } /// @@ -804,6 +872,7 @@ public: } /** */ ArgumentList argumentList; /** */ DeclarationsAndStatements declarationsAndStatements; + mixin OpEquals; } /// @@ -817,6 +886,7 @@ public: /** */ Type type; /** */ CastQualifier castQualifier; /** */ UnaryExpression unaryExpression; + mixin OpEquals; } /// @@ -829,6 +899,7 @@ public: } /** */ Token first; /** */ Token second; + mixin OpEquals; } /// @@ -841,6 +912,7 @@ public: } /** */ Catch[] catches; /** */ LastCatch lastCatch; + mixin OpEquals; } /// @@ -854,6 +926,7 @@ public: /** */ Type type; /** */ Token identifier; /** */ DeclarationOrStatement declarationOrStatement; + mixin OpEquals; } /// @@ -872,6 +945,7 @@ public: /** */ BaseClassList baseClassList; /** */ StructBody structBody; /** */ string comment; + mixin OpEquals; } /// @@ -888,6 +962,7 @@ public: /** */ ExpressionNode identityExpression; /** */ ExpressionNode relExpression; /** */ ExpressionNode inExpression; + mixin OpEquals; } /// @@ -901,6 +976,7 @@ public: /** */ VersionCondition versionCondition; /** */ DebugCondition debugCondition; /** */ StaticIfCondition staticIfCondition; + mixin OpEquals; } /// @@ -914,6 +990,7 @@ public: /** */ CompileCondition compileCondition; /** */ Declaration[] trueDeclarations; /** */ Declaration falseDeclaration; + mixin OpEquals; } /// @@ -927,6 +1004,7 @@ public: /** */ CompileCondition compileCondition; /** */ DeclarationOrStatement trueStatement; /** */ DeclarationOrStatement falseStatement; + mixin OpEquals; } /// @@ -938,6 +1016,7 @@ public: mixin (visitIfNotNull!(expression)); } /** */ Expression expression; + mixin OpEquals; } /// @@ -956,6 +1035,7 @@ public: /** */ TemplateParameters templateParameters; /** */ size_t location; /** */ string comment; + mixin OpEquals; } /// @@ -967,6 +1047,7 @@ public: mixin (visitIfNotNull!(label)); } /** */ Token label; + mixin OpEquals; } /// @@ -978,6 +1059,7 @@ public: mixin (visitIfNotNull!(identifierOrInteger)); } /** */ Token identifierOrInteger; + mixin OpEquals; } /// @@ -989,6 +1071,7 @@ public: mixin (visitIfNotNull!(identifierOrInteger)); } /** */ Token identifierOrInteger; + mixin OpEquals; } /// @@ -1008,7 +1091,7 @@ public: destructor, staticConstructor, staticDestructor, sharedStaticDestructor, sharedStaticConstructor, conditionalDeclaration, pragmaDeclaration, versionSpecification, - invariant_, postblit, declarations)); + invariant_, postblit, declarations)); } /** */ Attribute[] attributes; @@ -1040,6 +1123,7 @@ public: /** */ Invariant invariant_; /** */ Postblit postblit; /** */ Declaration[] declarations; + mixin OpEquals; } /// @@ -1051,6 +1135,7 @@ final class DeclarationsAndStatements : ASTNode } /** */ DeclarationOrStatement[] declarationsAndStatements; + mixin OpEquals; } /// @@ -1064,6 +1149,7 @@ public: /** */ Declaration declaration; /** */ Statement statement; + mixin OpEquals; } /// @@ -1076,6 +1162,7 @@ public: } /** */ Token name; /** */ Initializer initializer; + mixin OpEquals; } /// @@ -1087,6 +1174,7 @@ public: mixin (visitIfNotNull!(declarationsAndStatements)); } /** */ DeclarationsAndStatements declarationsAndStatements; + mixin OpEquals; } /// @@ -1098,8 +1186,9 @@ public: mixin (visitIfNotNull!(unaryExpression)); } /** */ UnaryExpression unaryExpression; - /** */ size_t line; - /** */ size_t column; + /** */ size_t line; + /** */ size_t column; + mixin OpEquals; } /// @@ -1111,6 +1200,7 @@ public: mixin (visitIfNotNull!(deleteExpression)); } /** */ DeleteExpression deleteExpression; + mixin OpEquals; } /// @@ -1122,6 +1212,7 @@ public: mixin (visitIfNotNull!(assignExpression)); } /** */ AssignExpression assignExpression; + mixin OpEquals; } /// @@ -1135,6 +1226,7 @@ public: /** */ FunctionBody functionBody; /** */ size_t location; /** */ string comment; + mixin OpEquals; } /// @@ -1147,6 +1239,7 @@ public: } /** */ StatementNoCaseNoDefault statementNoCaseNoDefault; /** */ Expression expression; + mixin OpEquals; } /// @@ -1168,6 +1261,7 @@ public: * Byte position of the closing brace */ size_t endLocation; + mixin OpEquals; } /// @@ -1182,6 +1276,7 @@ public: /** */ Type type; /** */ EnumBody enumBody; /** */ string comment; + mixin OpEquals; } /// @@ -1196,6 +1291,7 @@ public: /** */ Type type; /** */ AssignExpression assignExpression; /** */ string comment; + mixin OpEquals; } /// @@ -1209,6 +1305,7 @@ public: /** */ Token name; /** */ TemplateParameters templateParameters; /** */ AssignExpression assignExpression; + mixin OpEquals; } /// @@ -1221,6 +1318,7 @@ public: } /** */ IdType operator; mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -1232,6 +1330,7 @@ public: mixin (visitIfNotNull!(items)); } /** */ AssignExpression[] items; + mixin OpEquals; } /// @@ -1243,6 +1342,7 @@ public: mixin (visitIfNotNull!(expression)); } /** */ Expression expression; + mixin OpEquals; } /// @@ -1254,6 +1354,7 @@ public: mixin (visitIfNotNull!(switchStatement)); } /** */ SwitchStatement switchStatement; + mixin OpEquals; } /// @@ -1265,6 +1366,7 @@ public: mixin (visitIfNotNull!(declarationOrStatement)); } /** */ DeclarationOrStatement declarationOrStatement; + mixin OpEquals; } /// @@ -1280,7 +1382,8 @@ public: /** */ ExpressionStatement test; /** */ Expression increment; /** */ DeclarationOrStatement declarationOrStatement; - /** */ size_t startIndex; + /** */ size_t startIndex; + mixin OpEquals; } /// @@ -1294,11 +1397,12 @@ public: } /** */ IdType type; /** */ ForeachTypeList foreachTypeList; - /** */ ForeachType foreachType; + /** */ ForeachType foreachType; /** */ Expression low; /** */ Expression high; /** */ DeclarationOrStatement declarationOrStatement; - /** */ size_t startIndex; + /** */ size_t startIndex; + mixin OpEquals; } /// @@ -1312,6 +1416,7 @@ public: /** */ IdType[] typeConstructors; /** */ Type type; /** */ Token identifier; + mixin OpEquals; } /// @@ -1323,6 +1428,7 @@ public: mixin (visitIfNotNull!(items)); } /** */ ForeachType[] items; + mixin OpEquals; } /// @@ -1335,6 +1441,7 @@ public: } /** */ Token token; /** */ AtAttribute atAttribute; + mixin OpEquals; } /// @@ -1351,6 +1458,7 @@ public: /** */ BodyStatement bodyStatement; /** */ OutStatement outStatement; /** */ InStatement inStatement; + mixin OpEquals; } /// @@ -1361,10 +1469,11 @@ public: { mixin (visitIfNotNull!(type, unaryExpression, templateArguments, arguments)); } - /** */ Type type; + /** */ Type type; /** */ UnaryExpression unaryExpression; /** */ TemplateArguments templateArguments; /** */ Arguments arguments; + mixin OpEquals; } /// @@ -1376,6 +1485,7 @@ public: mixin (visitIfNotNull!(functionCallExpression)); } /** */ FunctionCallExpression functionCallExpression; + mixin OpEquals; } /// @@ -1397,6 +1507,7 @@ public: /** */ FunctionBody functionBody; /** */ MemberFunctionAttribute[] memberFunctionAttributes; /** */ string comment; + mixin OpEquals; } /// @@ -1413,6 +1524,7 @@ public: /** */ Parameters parameters; /** */ FunctionAttribute[] functionAttributes; /** */ FunctionBody functionBody; + mixin OpEquals; } /// @@ -1425,6 +1537,7 @@ public: } /** */ Expression expression; /** */ Token label; + mixin OpEquals; } /// @@ -1436,6 +1549,7 @@ public: mixin (visitIfNotNull!(identifiers)); } /** */ Token[] identifiers; + mixin OpEquals; } /// @@ -1447,6 +1561,7 @@ public: mixin (visitIfNotNull!(identifiers)); } /** */ Token[] identifiers; + mixin OpEquals; } /// @@ -1459,6 +1574,7 @@ public: } /** */ IdentifierOrTemplateInstance[] identifiersOrTemplateInstances; + mixin OpEquals; } /// @@ -1472,6 +1588,7 @@ public: /** */ Token identifier; /** */ TemplateInstance templateInstance; + mixin OpEquals; } /// @@ -1484,6 +1601,7 @@ public: } /** */ bool negated; mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -1500,7 +1618,10 @@ public: /** */ Expression expression; /** */ DeclarationOrStatement thenStatement; /** */ DeclarationOrStatement elseStatement; - /** */ size_t startIndex; + /** */ size_t startIndex; + /** */ size_t line; + /** */ size_t column; + mixin OpEquals; } /// @@ -1513,6 +1634,7 @@ public: } /** */ Token left; /** */ Token right; + mixin OpEquals; } /// @@ -1525,6 +1647,7 @@ public: } /** */ SingleImport singleImport; /** */ ImportBind[] importBinds; + mixin OpEquals; } /// @@ -1537,6 +1660,7 @@ public: } /** */ SingleImport[] singleImports; /** */ ImportBindings importBindings; + mixin OpEquals; } /// @@ -1548,6 +1672,7 @@ public: mixin (visitIfNotNull!(assignExpression)); } /** */ AssignExpression assignExpression; + mixin OpEquals; } /// @@ -1560,6 +1685,7 @@ public: } /** */ UnaryExpression unaryExpression; /** */ ArgumentList argumentList; + mixin OpEquals; } /// @@ -1572,6 +1698,7 @@ public: } mixin BinaryExpressionBody; bool negated; + mixin OpEquals; } /// @@ -1583,6 +1710,7 @@ public: mixin (visitIfNotNull!(blockStatement)); } /** */ BlockStatement blockStatement; + mixin OpEquals; } /// @@ -1594,6 +1722,7 @@ public: mixin (visitIfNotNull!(statementNoCaseNoDefault)); } /** */ StatementNoCaseNoDefault statementNoCaseNoDefault; + mixin OpEquals; } /// @@ -1605,6 +1734,7 @@ public: mixin (visitIfNotNull!(nonVoidInitializer)); } /** */ NonVoidInitializer nonVoidInitializer; + mixin OpEquals; } /// @@ -1622,6 +1752,7 @@ public: /** */ BaseClassList baseClassList; /** */ StructBody structBody; /** */ string comment; + mixin OpEquals; } /// @@ -1634,6 +1765,7 @@ public: } /** */ BlockStatement blockStatement; /** */ string comment; + mixin OpEquals; } /// @@ -1650,6 +1782,7 @@ public: /** */ TypeSpecialization typeSpecialization; /** */ TemplateParameterList templateParameterList; /** */ IdType equalsOrColon; + mixin OpEquals; } /// @@ -1662,6 +1795,7 @@ public: } /** */ AssignExpression key; /** */ AssignExpression value; + mixin OpEquals; } /// @@ -1673,6 +1807,7 @@ public: mixin (visitIfNotNull!(keyValuePairs)); } /** */ KeyValuePair[] keyValuePairs; + mixin OpEquals; } /// @@ -1685,6 +1820,7 @@ public: } Token identifier; /** */ DeclarationOrStatement declarationOrStatement; + mixin OpEquals; } /// @@ -1701,6 +1837,7 @@ public: /** */ Parameters parameters; /** */ FunctionAttribute[] functionAttributes; /** */ AssignExpression assignExpression; + mixin OpEquals; } /// @@ -1712,6 +1849,7 @@ public: mixin (visitIfNotNull!(statementNoCaseNoDefault)); } /** */ StatementNoCaseNoDefault statementNoCaseNoDefault; + mixin OpEquals; } /// @@ -1724,6 +1862,7 @@ public: } /** */ Token identifier; /** */ bool hasPlusPlus; + mixin OpEquals; } /// @@ -1736,6 +1875,7 @@ public: } /** */ IdType tokenType; /** */ AtAttribute atAttribute; + mixin OpEquals; } /// @@ -1748,6 +1888,7 @@ public: } /** */ MixinExpression mixinExpression; /** */ TemplateMixinExpression templateMixinExpression; + mixin OpEquals; } /// @@ -1759,6 +1900,7 @@ public: mixin (visitIfNotNull!(assignExpression)); } /** */ AssignExpression assignExpression; + mixin OpEquals; } /// @@ -1770,6 +1912,7 @@ public: mixin (visitIfNotNull!(templateDeclaration)); } /** */ TemplateDeclaration templateDeclaration; + mixin OpEquals; } /// @@ -1783,6 +1926,7 @@ public: /** */ Symbol symbol; /** */ IdentifierOrTemplateChain identifierOrTemplateChain; /** */ TypeofExpression typeofExpression; + mixin OpEquals; } /// @@ -1795,6 +1939,7 @@ public: } /** */ ModuleDeclaration moduleDeclaration; /** */ Declaration[] declarations; + mixin OpEquals; } /// @@ -1806,6 +1951,7 @@ public: mixin (visitIfNotNull!(moduleName)); } /** */ IdentifierChain moduleName; + mixin OpEquals; } @@ -1819,6 +1965,7 @@ public: } /** */ IdType operator; mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -1834,6 +1981,7 @@ public: /** */ Arguments constructorArguments; /** */ BaseClassList baseClassList; /** */ StructBody structBody; + mixin OpEquals; } /// @@ -1849,6 +1997,7 @@ public: /** */ NewAnonClassExpression newAnonClassExpression; /** */ Arguments arguments; /** */ AssignExpression assignExpression; + mixin OpEquals; } @@ -1892,6 +2041,7 @@ public: /** */ DebugSpecification debugSpecification; /** */ FunctionCallStatement functionCallStatement; /** */ ExpressionStatement expressionStatement; + mixin OpEquals; } /// @@ -1906,6 +2056,7 @@ public: /** */ ArrayInitializer arrayInitializer; /** */ StructInitializer structInitializer; + mixin OpEquals; } /// @@ -1914,6 +2065,7 @@ final class Operand : ASTNode public: mixin (DEFAULT_ACCEPT); /** */ AsmExp asmExp; + mixin OpEquals; } /// @@ -1922,6 +2074,7 @@ final class Operands : ASTNode public: mixin (DEFAULT_ACCEPT); /** */ Operand[] operands; + mixin OpEquals; } /// @@ -1933,6 +2086,7 @@ public: mixin (visitIfNotNull!(left, right)); } mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -1944,6 +2098,7 @@ public: mixin (visitIfNotNull!(left, right)); } mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -1956,6 +2111,7 @@ public: } /** */ Token parameter; /** */ BlockStatement blockStatement; + mixin OpEquals; } /// @@ -1972,6 +2128,7 @@ public: /** */ Token name; /** */ bool vararg; /** */ AssignExpression default_; + mixin OpEquals; } /// @@ -1985,6 +2142,7 @@ public: /** */ Parameter[] parameters; /** */ bool hasVarargs; + mixin OpEquals; } /// @@ -1996,6 +2154,7 @@ public: mixin (visitIfNotNull!(functionBody)); } /** */ FunctionBody functionBody; + mixin OpEquals; } /// @@ -2008,6 +2167,7 @@ public: } /** */ IdType operator; /** */ UnaryExpression unaryExpression; + mixin OpEquals; } /// @@ -2019,6 +2179,7 @@ public: mixin (visitIfNotNull!(left, right)); } mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -2030,6 +2191,7 @@ public: mixin (visitIfNotNull!(pragmaExpression)); } /** */ PragmaExpression pragmaExpression; + mixin OpEquals; } /// @@ -2042,6 +2204,7 @@ public: } /** */ Token identifier; /** */ ArgumentList argumentList; + mixin OpEquals; } /// @@ -2054,6 +2217,7 @@ public: } /** */ IdType operator; /** */ UnaryExpression unaryExpression; + mixin OpEquals; } /// @@ -2084,6 +2248,7 @@ public: /** */ MixinExpression mixinExpression; /** */ ImportExpression importExpression; /** */ Vector vector; + mixin OpEquals; } /// @@ -2094,6 +2259,7 @@ public: /** */ Token identifier; /** */ Token intLiteral; /** */ bool hasIntegerLiteral; + mixin OpEquals; } /// @@ -2106,6 +2272,7 @@ public: } /** */ IdType operator; mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -2117,6 +2284,7 @@ public: mixin (visitIfNotNull!(expression)); } /** */ Expression expression; + mixin OpEquals; } /// @@ -2129,6 +2297,7 @@ public: } /** */ Token identifier; /** */ StatementNoCaseNoDefault statementNoCaseNoDefault; + mixin OpEquals; } /// @@ -2142,6 +2311,7 @@ public: /** */ FunctionBody functionBody; /** */ size_t location; /** */ string comment; + mixin OpEquals; } /// @@ -2155,6 +2325,7 @@ public: /** */ FunctionBody functionBody; /** */ size_t location; /** */ string comment; + mixin OpEquals; } /// @@ -2167,6 +2338,7 @@ public: } /** */ IdType operator; mixin BinaryExpressionBody; + mixin OpEquals; } /// @@ -2179,6 +2351,7 @@ public: } /** */ Token rename; /** */ IdentifierChain identifierChain; + mixin OpEquals; } /// @@ -2192,6 +2365,7 @@ public: /** */ UnaryExpression unaryExpression; /** */ AssignExpression lower; /** */ AssignExpression upper; + mixin OpEquals; } /// @@ -2207,6 +2381,7 @@ public: /** */ CaseStatement caseStatement; /** */ CaseRangeStatement caseRangeStatement; /** */ DefaultStatement defaultStatement; + mixin OpEquals; } /// @@ -2218,6 +2393,7 @@ public: mixin (visitIfNotNull!(staticAssertStatement)); } /** */ StaticAssertStatement staticAssertStatement; + mixin OpEquals; } /// @@ -2229,6 +2405,7 @@ public: mixin (visitIfNotNull!(assertExpression)); } /** */ AssertExpression assertExpression; + mixin OpEquals; } /// @@ -2241,7 +2418,8 @@ public: } /** */ FunctionBody functionBody; /** */ size_t location; - /** */ string comment; + /** */ string comment; + mixin OpEquals; } /// @@ -2254,7 +2432,8 @@ public: } /** */ FunctionBody functionBody; /** */ size_t location; - /** */ string comment; + /** */ string comment; + mixin OpEquals; } /// @@ -2266,6 +2445,7 @@ public: mixin (visitIfNotNull!(assignExpression)); } /** */ AssignExpression assignExpression; + mixin OpEquals; } /// @@ -2279,6 +2459,7 @@ public: /** */ AtAttribute atAttribute; /** */ Deprecated deprecated_; /** */ Token token; + mixin OpEquals; } /// @@ -2300,6 +2481,7 @@ public: */ size_t endLocation; /** */ Declaration[] declarations; + mixin OpEquals; } /// @@ -2315,6 +2497,7 @@ public: /** */ Constraint constraint; /** */ StructBody structBody; /** */ string comment; + mixin OpEquals; } /// @@ -2327,6 +2510,7 @@ public: } /** */ StructMemberInitializers structMemberInitializers; + mixin OpEquals; } /// @@ -2339,6 +2523,7 @@ public: } /** */ Token identifier; /** */ NonVoidInitializer nonVoidInitializer; + mixin OpEquals; } /// @@ -2350,6 +2535,7 @@ public: mixin (visitIfNotNull!(structMemberInitializers)); } /** */ StructMemberInitializer[] structMemberInitializers; + mixin OpEquals; } /// @@ -2362,6 +2548,7 @@ public: } /** */ Expression expression; /** */ Statement statement; + mixin OpEquals; } /// @@ -2375,6 +2562,7 @@ public: /** */ IdentifierOrTemplateChain identifierOrTemplateChain; /** */ bool dot; + mixin OpEquals; } /// @@ -2387,6 +2575,7 @@ public: } /** */ Expression expression; /** */ StatementNoCaseNoDefault statementNoCaseNoDefault; + mixin OpEquals; } /// @@ -2404,6 +2593,7 @@ public: /** */ AssignExpression colonExpression; /** */ Type assignType; /** */ AssignExpression assignExpression; + mixin OpEquals; } /// @@ -2416,6 +2606,7 @@ public: } /** */ Type type; /** */ AssignExpression assignExpression; + mixin OpEquals; } /// @@ -2427,6 +2618,7 @@ public: mixin (visitIfNotNull!(items)); } /** */ TemplateArgument[] items; + mixin OpEquals; } /// @@ -2439,6 +2631,7 @@ public: } /** */ TemplateArgumentList templateArgumentList; /** */ TemplateSingleArgument templateSingleArgument; + mixin OpEquals; } /// @@ -2456,6 +2649,7 @@ public: /** */ Declaration[] declarations; /** */ EponymousTemplateDeclaration eponymousTemplateDeclaration; /** */ string comment; + mixin OpEquals; } /// @@ -2468,6 +2662,7 @@ public: } /** */ Token identifier; /** */ TemplateArguments templateArguments; + mixin OpEquals; } /// @@ -2481,6 +2676,7 @@ public: /** */ Token identifier; /** */ TemplateArguments templateArguments; /** */ MixinTemplateName mixinTemplateName; + mixin OpEquals; } /// @@ -2498,6 +2694,7 @@ public: /** */ TemplateAliasParameter templateAliasParameter; /** */ TemplateTupleParameter templateTupleParameter; /** */ TemplateThisParameter templateThisParameter; + mixin OpEquals; } /// @@ -2509,6 +2706,7 @@ public: mixin (visitIfNotNull!(items)); } /** */ TemplateParameter[] items; + mixin OpEquals; } /// @@ -2520,6 +2718,7 @@ public: mixin (visitIfNotNull!(templateParameterList)); } /** */ TemplateParameterList templateParameterList; + mixin OpEquals; } /// @@ -2531,6 +2730,7 @@ public: mixin (visitIfNotNull!(token)); } /** */ Token token; + mixin OpEquals; } /// @@ -2542,6 +2742,7 @@ public: mixin (visitIfNotNull!(templateTypeParameter)); } /** */ TemplateTypeParameter templateTypeParameter; + mixin OpEquals; } /// @@ -2553,6 +2754,7 @@ public: mixin (visitIfNotNull!(identifier)); } /** */ Token identifier; + mixin OpEquals; } /// @@ -2566,6 +2768,7 @@ public: /** */ Token identifier; /** */ Type colonType; /** */ Type assignType; + mixin OpEquals; } /// @@ -2581,6 +2784,7 @@ public: /** */ Token identifier; /** */ Expression expression; /** */ TemplateValueParameterDefault templateValueParameterDefault; + mixin OpEquals; } /// @@ -2593,6 +2797,7 @@ public: } /** */ AssignExpression assignExpression; /** */ Token token; + mixin OpEquals; } /// @@ -2606,6 +2811,7 @@ public: /** */ ExpressionNode orOrExpression; /** */ ExpressionNode expression; /** */ ExpressionNode ternaryExpression; + mixin OpEquals; } /// @@ -2617,6 +2823,7 @@ public: mixin (visitIfNotNull!(expression)); } /** */ Expression expression; + mixin OpEquals; } /// @@ -2629,6 +2836,7 @@ public: } /** */ Token identifier; /** */ TemplateArgumentList templateArgumentList; + mixin OpEquals; } /// @@ -2642,6 +2850,7 @@ public: /** */ DeclarationOrStatement declarationOrStatement; /** */ Catches catches; /** */ Finally finally_; + mixin OpEquals; } /// @@ -2656,6 +2865,7 @@ public: /** */ IdType[] typeConstructors; /** */ TypeSuffix[] typeSuffixes; /** */ Type2 type2; + mixin OpEquals; } /// @@ -2674,6 +2884,7 @@ public: /** */ IdentifierOrTemplateChain identifierOrTemplateChain; /** */ IdType typeConstructor; /** */ Type type; + mixin OpEquals; } /// @@ -2686,6 +2897,7 @@ public: } /** */ Token token; /** */ Type type; + mixin OpEquals; } /// @@ -2706,6 +2918,7 @@ public: /** */ AssignExpression high; /** */ Parameters parameters; /** */ MemberFunctionAttribute[] memberFunctionAttributes; + mixin OpEquals; } /// @@ -2718,6 +2931,7 @@ public: } /** */ Type type; /** */ Expression expression; + mixin OpEquals; } /// @@ -2728,8 +2942,14 @@ public: { mixin (visitIfNotNull!(expression, return_)); } + + override bool opEquals(Object other) const + { + mixin (generateOpEquals!(typeof(this))); + } /** */ Expression expression; /** */ Token return_; + mixin OpEquals; } /// @@ -2745,6 +2965,11 @@ public: sliceExpression, indexExpression)); } + override bool opEquals(Object other) const + { + mixin (generateOpEquals!(typeof(this))); + } + /** */ Type type; /** */ PrimaryExpression primaryExpression; /** */ Token prefix; @@ -2759,6 +2984,7 @@ public: /** */ AssertExpression assertExpression; /** */ SliceExpression sliceExpression; /** */ IndexExpression indexExpression; + mixin OpEquals; } /// @@ -2775,6 +3001,7 @@ public: /** */ Constraint constraint; /** */ StructBody structBody; /** */ string comment; + mixin OpEquals; } /// @@ -2787,6 +3014,7 @@ public: } /** */ BlockStatement blockStatement; /** */ string comment; + mixin OpEquals; } /// @@ -2802,6 +3030,7 @@ public: /** */ StorageClass storageClass; /** */ AutoDeclaration autoDeclaration; /** */ string comment; + mixin OpEquals; } /// @@ -2813,6 +3042,7 @@ public: mixin (visitIfNotNull!(type)); } /** */ Type type; + mixin OpEquals; } /// @@ -2824,6 +3054,7 @@ public: mixin (visitIfNotNull!(token)); } /** */ Token token; + mixin OpEquals; } /// @@ -2835,6 +3066,7 @@ public: mixin (visitIfNotNull!(token)); } /** */ Token token; + mixin OpEquals; } /// @@ -2848,7 +3080,8 @@ public: /** */ Expression expression; /** */ DeclarationOrStatement declarationOrStatement; - /** */ size_t startIndex; + /** */ size_t startIndex; + mixin OpEquals; } /// @@ -2862,6 +3095,7 @@ public: /** */ Expression expression; /** */ StatementNoCaseNoDefault statementNoCaseNoDefault; + mixin OpEquals; } /// @@ -2873,4 +3107,5 @@ public: mixin (visitIfNotNull!(left, right)); } mixin BinaryExpressionBody; + mixin OpEquals; } diff --git a/stdx/d/lexer.d b/stdx/d/lexer.d index 31b15d7..5c0853d 100644 --- a/stdx/d/lexer.d +++ b/stdx/d/lexer.d @@ -557,7 +557,7 @@ public struct DLexer Token lexNumber() pure nothrow { mixin (tokenStart); - if (range.canPeek(1) && range.front == '0') + if (range.front == '0' && range.canPeek(1)) { auto ahead = range.peek(1)[1]; switch (ahead) diff --git a/stdx/d/parser.d b/stdx/d/parser.d index a95ec5a..c2b4103 100644 --- a/stdx/d/parser.d +++ b/stdx/d/parser.d @@ -780,6 +780,8 @@ alias core.sys.posix.stdio.fileno fileno; { mixin(traceEnterAndExit!(__FUNCTION__)); auto node = allocate!AssignExpression; + node.line = current().line; + node.column = current().column; node.ternaryExpression = parseTernaryExpression(); if (currentIsOneOf(tok!"=", tok!">>>=", tok!">>=", tok!"<<=", @@ -2872,6 +2874,8 @@ body {} // six { mixin(traceEnterAndExit!(__FUNCTION__)); auto node = allocate!IfStatement; + node.line = current().line; + node.column = current().column; if (expect(tok!"if") is null) return null; node.startIndex = current().index; if (expect(tok!"(") is null) return null;