@Override public Expression semantic(Scope sc, SemanticContext context) { if (type != null) { return this; } /* This is here to support extern(linkage) declaration, * where the extern(linkage) winds up being an AttribDeclaration * wrapper. */ Dsymbol s = declaration; AttribDeclaration ad = declaration.isAttribDeclaration(); if (ad != null) { if (ad.decl != null && ad.decl.size() == 1) { s = ad.decl.get(0); } } if (s.isVarDeclaration() != null) { // Do semantic() on initializer first, so: // int a = a; // will be illegal. declaration.semantic(sc, context); s.parent = sc.parent; } // Insert into both local scope and function scope. // Must be unique in both. if (s.ident != null) { if (sc.insert(s) == null) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeErrorLoc( IProblem.DeclarationIsAlreadyDefined, s, s.toChars(context))); } } else if (sc.func != null) { // VarDeclaration v = s.isVarDeclaration(); if ((s.isFuncDeclaration() != null /*|| v && v.storage_class & STCstatic*/) && sc.func.localsymtab.insert(s) == null) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeError( IProblem.DeclarationIsAlreadyDefinedInAnotherScope, this, s.toPrettyChars(context), sc.func.toChars(context))); } } else if (!context.global.params.useDeprecated) { // Disallow shadowing for (Scope scx = sc.enclosing; scx != null && scx.func == sc.func; scx = scx.enclosing) { Dsymbol s2; if (scx.scopesym != null && scx.scopesym.symtab != null && (s2 = scx.scopesym.symtab.lookup(s.ident)) != null && s != s2) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeErrorLoc( IProblem.ShadowingDeclarationIsDeprecated, s, s.toPrettyChars(context))); } } } } } } if (s.isVarDeclaration() == null) { declaration.semantic(sc, context); s.parent = sc.parent; } // Commented this for Descent: we want semantic even if there are errors // if (context.global.errors == 0) { declaration.semantic2(sc, context); // if (context.global.errors == 0) { declaration.semantic3(sc, context); // } // } type = Type.tvoid; return this; }
@Override public Statement semantic(Scope sc, SemanticContext context) { SwitchStatement sw = sc.sw; this.sw = sw; exp = exp.semantic(sc, context); if (sw != null) { int i; exp = exp.implicitCastTo(sc, sw.condition.type, context); exp = exp.optimize(WANTvalue | WANTinterpret, context); boolean gotoL1 = false; if (context.isD2()) { /* This is where variables are allowed as case expressions. */ if (exp.op == TOKvar) { VarExp ve = (VarExp) exp; VarDeclaration v = ve.var.isVarDeclaration(); Type t = exp.type.toBasetype(context); if (v != null && (t.isintegral() || t.ty == Tclass)) { /* Flag that we need to do special code generation * for this, i.e. generate a sequence of if-then-else */ sw.hasVars = 1; // goto L1; gotoL1 = true; } } } if (!gotoL1) { if (exp.op != TOKstring && exp.op != TOKint64) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeError( IProblem.CaseMustBeAnIntegralOrStringConstant, sourceExp, exp.toChars(context))); } exp = new IntegerExp(0); } } // L1: for (i = 0; i < sw.cases.size(); i++) { CaseStatement cs = (CaseStatement) sw.cases.get(i); if (cs.exp.equals(exp, context)) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeErrorLoc( IProblem.DuplicateCaseInSwitchStatement, this, exp.toChars(context))); } break; } } sw.cases.add(this); // Resolve any goto case's with no exp to this case statement if (sw.gotoCases != null) { for (i = 0; i < sw.gotoCases.size(); i++) { GotoCaseStatement gcs = (GotoCaseStatement) sw.gotoCases.get(i); if (gcs.exp == null) { gcs.cs = this; sw.gotoCases.remove(i); // remove from array } } } if (context.isD2()) { if (sc.sw.tf != sc.tf) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeErrorLoc( IProblem.SwitchAndCaseAreInDifferentFinallyBlocks, this)); } } } } else { if (context.acceptsErrors()) { context.acceptProblem(Problem.newSemanticTypeError(IProblem.CaseIsNotInSwitch, this)); } } statement = statement.semantic(sc, context); return this; }