Logo Search packages:      
Sourcecode: jikes version File versions  Download package

definite.cpp

// $Id: definite.cpp,v 1.69 2004/06/02 10:28:06 elliott-oss Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler
// License Agreement available at the following URL:
// http://ibm.com/developerworks/opensource/jikes.
// Copyright (C) 1996, 2004 IBM Corporation and others.  All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
#include "platform.h"
#include "semantic.h"
#include "control.h"
#include "option.h"

#ifdef HAVE_JIKES_NAMESPACE
namespace Jikes { // Open namespace Jikes block
#endif

//
// NOTE: This file is used to determine definite assignment and definite
// unassignment rules, per JLS chapter 16.  Often, these are abbreviated
// da and du.  The BitSet type holds a status bit for every variable in
// scope.  Since many rules operate identically on da and du, the DefinitePair
// type is a wrapper for two BitSets.  Finally, boolean expressions can
// cause different definite assignment status during speculation, so
// the DefiniteAssignmentSet is a wrapper for two DefinitePair objects.
//
// It is a compile-time error if a local variable is accessed that is not
// da, and a compile-time error if a blank final is assigned when it is
// not du.  This code also handles the compile-time error when an assignment
// is attempted to an initialized final.
//
// There are two contexts: expression and statement.  In expression context,
// we must pass in the current assignment state and return the resultant
// state (if different) - this is to allow speculative decisions when
// evaluating loop bodies.  In statement context, rather than pass the
// information around, we store it in the instance variable
// *DefinitelyAssignedVariables() for efficiency.
//

inline DefinitePair::DefinitePair(const DefiniteAssignmentSet& set)
    : da_set(set.DASet()),
      du_set(set.DUSet())
{}

inline DefinitePair& DefinitePair::operator=(const DefiniteAssignmentSet& rhs)
{
    da_set = rhs.DASet();
    du_set = rhs.DUSet();
    return *this;
}


//
// There are two versions of DefiniteExpression.  Call this version if the
// expression can be boolean, but there is no need to track the when true
// and when false cases separately; or if the expression cannot be boolean.
// If the expression can be (or always is) boolean, and the when true and
// when false cases matter, call DefiniteBooleanExpression.
//
void Semantic::DefiniteExpression(AstExpression* expr, DefinitePair& def_pair)
{
    if (expr -> IsConstant()) // A constant expression has no effect on DA/DU.
        return;
    DefiniteAssignmentSet* definite = DefiniteBooleanExpression(expr,
                                                                def_pair);
    if (definite)
    {
        def_pair = *definite;
        delete definite;
    }
}

//
// See the comments for DefiniteExpression above.  If the when true and when
// false status differ after this expression, the calling function MUST delete
// the returned object to avoid a memory leak.
//
DefiniteAssignmentSet* Semantic::DefiniteBooleanExpression(AstExpression* expr,
                                                           DefinitePair& def_pair)
{
    DefiniteAssignmentSet* definite = NULL;

    //
    // Is the expression a constant expression of type boolean?
    // Recall that a constant expression does not contain an
    // assignment statement.
    //
    if (IsConstantTrue(expr))
        return new DefiniteAssignmentSet(def_pair, *Universe());
    else if (IsConstantFalse(expr))
        return new DefiniteAssignmentSet(*Universe(), def_pair);
    else if (expr -> symbol != control.no_type)
        definite = (this ->* DefiniteExpr[expr -> kind])(expr, def_pair);

    assert(! definite || expr -> Type() == control.boolean_type);
    return definite;
}


DefiniteAssignmentSet* Semantic::DefiniteName(AstExpression* expression,
                                              DefinitePair& def_pair)
{
    AstName* name = (AstName*) expression;

    if (name -> resolution_opt)
        return DefiniteBooleanExpression(name -> resolution_opt, def_pair);
    if (name -> base_opt)
        DefiniteName(name -> base_opt, def_pair);

    //
    // Some simple names are undefined. e.g., the simple name in a method call.
    // Others were generated by the compiler as method shadows, so we know
    // when and where they will be properly initialized. Qualified names are
    // always treated as initialized.
    //
    VariableSymbol* variable = name -> symbol
        ? name -> symbol -> VariableCast() : (VariableSymbol*) NULL;
    if (variable && ! variable -> ACC_SYNTHETIC() && ! name -> base_opt &&
        (variable -> IsLocal(ThisMethod()) || variable -> IsFinal(ThisType())))
    {
        int index = variable -> LocalVariableIndex(this);
        //
        // Compile time constants are always da; this matters in switch
        // blocks, where we might have bypassed the initializer.
        //
        if (! def_pair.da_set[index] && ! name -> IsConstant())
        {
            ReportSemError(SemanticError::VARIABLE_NOT_DEFINITELY_ASSIGNED,
                           name -> identifier_token, variable -> Name());

            if (variable -> IsLocal(ThisMethod())) // avoid cascading errors!
                def_pair.da_set.AddElement(index);
        }
    }
    return NULL;
}


DefiniteAssignmentSet* Semantic::DefiniteArrayAccess(AstExpression* expression,
                                                     DefinitePair& def_pair)
{
    AstArrayAccess* array_access = (AstArrayAccess*) expression;
    DefiniteExpression(array_access -> base, def_pair);
    DefiniteExpression(array_access -> expression, def_pair);
    return NULL;
}


DefiniteAssignmentSet* Semantic::DefiniteMethodInvocation(AstExpression* expression,
                                                          DefinitePair& def_pair)
{
    AstMethodInvocation* method_call = (AstMethodInvocation*) expression;
    if (method_call -> base_opt)
        DefiniteExpression(method_call -> base_opt, def_pair);
    for (unsigned i = 0; i < method_call -> arguments -> NumArguments(); i++)
        DefiniteExpression(method_call -> arguments -> Argument(i), def_pair);
    return NULL;
}


DefiniteAssignmentSet* Semantic::DefiniteClassCreationExpression(AstExpression* expression,
                                                                 DefinitePair& def_pair)
{
    unsigned i;
    AstClassCreationExpression* class_creation =
        (AstClassCreationExpression*) expression;
    if (class_creation -> resolution_opt)
        class_creation = class_creation -> resolution_opt;
    if (class_creation -> base_opt)
        DefiniteExpression(class_creation -> base_opt, def_pair);
    for (i = 0; i < class_creation -> arguments -> NumArguments(); i++)
        DefiniteExpression(class_creation -> arguments -> Argument(i),
                           def_pair);
    for (i = 0; i < class_creation -> arguments -> NumLocalArguments(); i++)
        DefiniteExpression(class_creation -> arguments -> LocalArgument(i),
                           def_pair);
    return NULL;
}


DefiniteAssignmentSet* Semantic::DefiniteArrayCreationExpression(AstExpression* expression,
                                                                 DefinitePair& def_pair)
{
    AstArrayCreationExpression* array_creation =
        (AstArrayCreationExpression*) expression;

    for (unsigned i = 0; i < array_creation -> NumDimExprs(); i++)
    {
        AstDimExpr* dim_expr = array_creation -> DimExpr(i);
        DefiniteExpression(dim_expr -> expression, def_pair);
    }

    if (array_creation -> array_initializer_opt)
        DefiniteArrayInitializer(array_creation -> array_initializer_opt,
                                 def_pair);
    return NULL;
}


inline VariableSymbol* Semantic::DefiniteFinal(AstFieldAccess* field_access)
{
    if (field_access -> resolution_opt)
        field_access = field_access -> resolution_opt -> FieldAccessCast();

    if (field_access)
    {
        VariableSymbol* variable = (field_access -> symbol
                                    ? field_access -> symbol -> VariableCast()
                                    : (VariableSymbol*) NULL);
        if (variable && variable -> IsFinal(ThisType()))
        {
            //
            // There is exactly one copy of a static variable, so, it's
            // always the right one. Access via 'this' is also legal.
            //
            if (variable -> ACC_STATIC() ||
                field_access -> base -> ThisExpressionCast())
            {
                return variable;
            }
        }
    }
    return NULL;
}


DefiniteAssignmentSet* Semantic::DefinitePLUSPLUSOrMINUSMINUS(AstExpression* expr,
                                                              DefinitePair& def_pair)
{
    DefiniteExpression(expr, def_pair);

    //
    // JLS2 added ability for parenthesized variable to remain a variable
    //
    while (expr -> ParenthesizedExpressionCast())
        expr = ((AstParenthesizedExpression*) expr) -> expression;

    VariableSymbol* variable = NULL;
    if (! expr -> ArrayAccessCast()) // some kind of name
    {
        MethodSymbol* read_method = NULL;
        AstName* name = expr -> NameCast();
        if (name)
        {
            if (name -> resolution_opt)
                read_method = name -> resolution_opt -> symbol -> MethodCast();
        }
        else
        {
            AstFieldAccess* field_access = expr -> FieldAccessCast();
            assert(field_access);

            if (field_access -> resolution_opt)
                read_method =
                    field_access -> resolution_opt -> symbol -> MethodCast();
        }

        variable = (read_method
                    ? (VariableSymbol*) read_method -> accessed_member
                    : expr -> symbol -> VariableCast());
        while (variable && variable -> accessed_local)
            variable = variable -> accessed_local;
    }

    //
    // If we have a variable and it is final then...
    //
    if (variable && variable -> ACC_FINAL())
    {
        if ((variable -> IsLocal(ThisMethod()) ||
             variable -> IsFinal(ThisType())) &&
            ! variable -> ACC_SYNTHETIC() &&
            (*BlankFinals())[variable -> LocalVariableIndex(this)])
        {
            ReportSemError(SemanticError::VARIABLE_NOT_DEFINITELY_UNASSIGNED,
                           expr -> LeftToken(),
                           expr -> RightToken(),
                           variable -> Name());
        }
        else
        {
            ReportSemError(SemanticError::FINAL_VARIABLE_NOT_BLANK,
                           expr -> LeftToken(),
                           expr -> RightToken(),
                           variable -> Name());
        }

        // Mark it assigned, to catch further errors.
        if (variable -> IsFinal(ThisType()) && ! variable -> ACC_SYNTHETIC())
            def_pair.du_set.RemoveElement(variable -> LocalVariableIndex(this));
    }
    return NULL;
}


DefiniteAssignmentSet* Semantic::DefinitePostUnaryExpression(AstExpression* expression,
                                                             DefinitePair& def_pair)
{
    AstPostUnaryExpression* postfix_expression =
        (AstPostUnaryExpression*) expression;
    return DefinitePLUSPLUSOrMINUSMINUS(postfix_expression -> expression,
                                        def_pair);
}


DefiniteAssignmentSet* Semantic::DefiniteNOT(AstExpression* expr,
                                             DefinitePair& def_pair)
{
    DefiniteAssignmentSet* after_expr = DefiniteBooleanExpression(expr,
                                                                  def_pair);
    if (after_expr) // is the expression is a complex boolean expression?
    {
        DefinitePair temp(after_expr -> true_pair);
        after_expr -> true_pair = after_expr -> false_pair;
        after_expr -> false_pair = temp;
    }
    return after_expr;
}


//
// The default pre unary operators are +, -, and ~.
// As these operators are not applicable to boolean expressions,
// we do not need to invoke DefiniteExpression to process them.
//
DefiniteAssignmentSet* Semantic::DefiniteDefaultPreUnaryExpression(AstExpression* expr,
                                                                   DefinitePair& def_pair)
{
    return (this ->* DefiniteExpr[expr -> kind])(expr, def_pair);
}


DefiniteAssignmentSet* Semantic::DefinitePreUnaryExpression(AstExpression* expression,
                                                            DefinitePair& def_pair)
{
    AstPreUnaryExpression* prefix_expression =
        (AstPreUnaryExpression*) expression;
    return (this ->* DefinitePreUnaryExpr[prefix_expression -> Tag()])
        (prefix_expression -> expression, def_pair);
}


DefiniteAssignmentSet* Semantic::DefiniteAND_AND(AstBinaryExpression* expr,
                                                 DefinitePair& def_pair)
{
    DefiniteAssignmentSet* after_left =
        DefiniteBooleanExpression(expr -> left_expression, def_pair);
    DefinitePair* before_right = NULL;
    if (after_left)
        def_pair = after_left -> true_pair;
    else
        before_right = new DefinitePair(def_pair);

    DefiniteAssignmentSet* after_right =
        DefiniteBooleanExpression(expr -> right_expression, def_pair);

    if (after_left)
    {
        if (after_right)
        {
            after_right -> false_pair *= after_left -> false_pair;
            delete after_left;
        }
        else
        {
            after_right = after_left;
            after_right -> true_pair = def_pair;
            after_right -> false_pair *= def_pair;
        }
    }
    else
    {
        if (! after_right)
            after_right = new DefiniteAssignmentSet(def_pair);

        after_right -> false_pair *= *before_right;
    }

    // harmless if NULL
    delete before_right;
    return after_right;
}


DefiniteAssignmentSet* Semantic::DefiniteOR_OR(AstBinaryExpression* expr,
                                               DefinitePair& def_pair)
{
    DefiniteAssignmentSet* after_left =
        DefiniteBooleanExpression(expr -> left_expression, def_pair);
    DefinitePair* before_right = NULL;
    if (after_left)
        def_pair = after_left -> false_pair;
    else
        before_right = new DefinitePair(def_pair);

    DefiniteAssignmentSet* after_right =
        DefiniteBooleanExpression(expr -> right_expression, def_pair);

    if (after_left)
    {
        if (after_right)
        {
            after_right -> true_pair *= after_left -> true_pair;
            delete after_left;
        }
        else
        {
            after_right = after_left;
            after_right -> true_pair *= def_pair;
            after_right -> false_pair = def_pair;
        }
    }
    else
    {
        if (! after_right)
            after_right = new DefiniteAssignmentSet(def_pair);

        after_right -> true_pair *= *before_right;
    }

    // harmless if NULL
    delete before_right;
    return after_right;
}


DefiniteAssignmentSet* Semantic::DefiniteDefaultBinaryExpression(AstBinaryExpression* expr,
                                                                 DefinitePair& def_pair)
{
    DefiniteExpression(expr -> left_expression, def_pair);
    DefiniteExpression(expr -> right_expression, def_pair);
    return NULL;
}


DefiniteAssignmentSet* Semantic::DefiniteBinaryExpression(AstExpression* expression,
                                                          DefinitePair& def_pair)
{
    AstBinaryExpression* binary_expression =
        (AstBinaryExpression*) expression;
    return (this ->* DefiniteBinaryExpr[binary_expression -> Tag()])
        (binary_expression, def_pair);
}


DefiniteAssignmentSet* Semantic::DefiniteInstanceofExpression(AstExpression* expression,
                                                              DefinitePair& def_pair)
{
    AstInstanceofExpression* expr = (AstInstanceofExpression*) expression;
    DefiniteExpression(expr -> expression, def_pair);
    return NULL;
}


DefiniteAssignmentSet* Semantic::DefiniteConditionalExpression(AstExpression* expression,
                                                               DefinitePair& def_pair)
{
    AstConditionalExpression* conditional_expression =
        (AstConditionalExpression*) expression;

    DefiniteAssignmentSet* after_condition =
        DefiniteBooleanExpression(conditional_expression -> test_expression,
                                  def_pair);
    DefinitePair* before_expressions = NULL;

    if (after_condition)
        def_pair = after_condition -> true_pair;
    else before_expressions = new DefinitePair(def_pair);
    DefiniteAssignmentSet* after_true =
        DefiniteBooleanExpression(conditional_expression -> true_expression,
                                  def_pair);
    DefinitePair* after_true_pair = (after_true ? (DefinitePair*) NULL
                                     : new DefinitePair(def_pair));

    if (after_condition)
         def_pair = after_condition -> false_pair;
    else def_pair = *before_expressions;
    DefiniteAssignmentSet* after_false =
        DefiniteBooleanExpression(conditional_expression -> false_expression,
                                  def_pair);

    if (conditional_expression -> Type() == control.boolean_type)
    {
        if (! after_true)
            after_true = new DefiniteAssignmentSet(*after_true_pair);

        if (after_false)
        {
            after_true -> true_pair *= after_false -> true_pair;
            after_true -> false_pair *= after_false -> false_pair;
        }
        else
        {
            after_true -> true_pair *= def_pair;
            after_true -> false_pair *= def_pair;
        }
    }
    else
    {
        assert(! after_true && ! after_false);
        def_pair *= *after_true_pair;
    }

    // harmless if NULL
    delete after_condition;
    delete before_expressions;
    delete after_false;
    return after_true;
}


DefiniteAssignmentSet* Semantic::DefiniteAssignmentExpression(AstExpression* expression,
                                                              DefinitePair& def_pair)
{
    AstAssignmentExpression* assignment_expression =
        (AstAssignmentExpression*) expression;

    AstCastExpression* casted_left_hand_side =
        assignment_expression -> left_hand_side -> CastExpressionCast();
    AstExpression* left_hand_side = casted_left_hand_side
        ? casted_left_hand_side -> expression
        : assignment_expression -> left_hand_side;
    bool simple_name = false;
    if (left_hand_side -> NameCast())
    {
        AstName* name = (AstName*) left_hand_side;
        simple_name = ! name -> base_opt;
    }
    else
    {
        AstFieldAccess* field_access = left_hand_side -> FieldAccessCast();
        if (field_access)
        {
            if (field_access -> resolution_opt)
                left_hand_side = field_access -> resolution_opt;
            //
            // Because constructor parameters often shadow field names,
            // this.name is legal for final instance fields. However, anything
            // more complex, such as (this).name or Classname.this.name, as
            // well as Classname.name for static fields or expression.name in
            // general, will be rejected.
            // TODO: This is not well-specified in the JLS; rather we are just
            // following the lead of Sun's javac 1.4.1. Clean this code up when
            // a decent specification is given.
            //
            if (field_access -> base -> ThisExpressionCast())
                simple_name = ((AstThisExpression*) field_access -> base) ->
                    base_opt == NULL;
        }
    }

    VariableSymbol* variable = (left_hand_side -> symbol
                                ? left_hand_side -> symbol -> VariableCast()
                                : (VariableSymbol*) NULL);
    while (variable && variable -> accessed_local)
        variable = variable -> accessed_local;
    int index = 0;

    //
    // An array access is never considered to be final. Since no variable
    // is associated with the array access, the testing for the presence of
    // variable takes care of that possibility.
    //
    if (variable)
    {
        if (variable -> IsLocal(ThisMethod()) ||
            variable -> IsFinal(ThisType()))
        {
            index = variable -> LocalVariableIndex(this);

            //
            // If we have a compound assignment then the variable must have
            // been set prior to such an assignment. otherwise, an error
            // occurs.
            //
            if (! assignment_expression -> SimpleAssignment() &&
                ! def_pair.da_set[index])
            {
                ReportSemError(SemanticError::VARIABLE_NOT_DEFINITELY_ASSIGNED,
                               left_hand_side -> LeftToken(),
                               left_hand_side -> RightToken(),
                               variable -> Name());
            }
        }
        else if (variable -> ACC_FINAL())
        {
            // attempt to assign a value to a final field member!
            ReportSemError(SemanticError::FINAL_VARIABLE_NOT_BLANK,
                           left_hand_side -> LeftToken(),
                           left_hand_side -> RightToken(),
                           variable -> Name());
        }
    }

    //
    // The left-hand-side of an assignment expression is either a simple name,
    // a field access or an array access.  A simple name does not need further
    // action, a field access needs to descend into all qualifying expressions,
    // and an array access needs to descend into the entire expression.
    //
    if (! simple_name)
    {
        AstFieldAccess* field_access = left_hand_side -> FieldAccessCast();
        DefiniteExpression((field_access ? field_access -> base
                            : left_hand_side),
                           def_pair);
    }

    //
    // JLS2 16.1.7 - The rules for definite assignment of boolean valued
    // assignments are stricter than they were in JLS1; hence we no longer
    // consider the when true and when false values separately.
    //
    DefiniteExpression(assignment_expression -> expression, def_pair);

    //
    // Finally, we mark the variable as assigned.
    //
    if (variable &&
        (variable -> IsLocal(ThisMethod()) || variable -> IsFinal(ThisType())))
    {
        if (variable -> ACC_FINAL())
        {
            //
            // It is an error to assign finals except for DU blank final. Also,
            // final fields must be assigned by simple name, or by this.name.
            //
            if (! (*BlankFinals())[index] || ! def_pair.du_set[index])
            {
                ReportSemError(((*BlankFinals())[index]
                                ? SemanticError::VARIABLE_NOT_DEFINITELY_UNASSIGNED
                                : SemanticError::FINAL_VARIABLE_NOT_BLANK),
                               left_hand_side -> LeftToken(),
                               left_hand_side -> RightToken(),
                               variable -> Name());
            }
            else if (variable -> IsFinal(ThisType()) && ! simple_name)
            {
                ReportSemError(SemanticError::FINAL_FIELD_ASSIGNMENT_NOT_SIMPLE,
                               left_hand_side -> LeftToken(),
                               left_hand_side -> RightToken(),
                               variable -> Name(),
                               (variable -> ACC_STATIC() ? NULL
                                : variable -> Name()));
            }
            else if (! def_pair.da_set[index])
            {
                //
                // If the variable is also DA, then this code is never
                // executed, so it does not affect loop or try-catch analysis.
                //
                if (DefiniteFinalAssignments() -> Size() > 0)
                {
                    DefiniteFinalAssignments() -> Top().Next() =
                        left_hand_side;
                }
                ReachableAssignments() -> AddElement(index);
            }
        }

        def_pair.AssignElement(index);
    }
    return NULL;
}

DefiniteAssignmentSet* Semantic::DefiniteParenthesizedExpression(AstExpression* expression,
                                                                 DefinitePair& def_pair)
{
    AstParenthesizedExpression* expr =
        (AstParenthesizedExpression*) expression;
    return DefiniteBooleanExpression(expr -> expression, def_pair);
}

DefiniteAssignmentSet* Semantic::DefiniteFieldAccess(AstExpression* expression,
                                                     DefinitePair& def_pair)
{
    AstFieldAccess* expr = (AstFieldAccess*) expression;

    //
    // TODO: Sun bug 4395322 mentions that DA is underspecified for field
    // references.  In other words, it is legal to read an uninitialized
    // static value through Classname.fieldname, or an instance value
    // through this.fieldname. If Sun specifies that this behavior is correct,
    // this commented code can be removed.
    //
    //      VariableSymbol* variable = DefiniteFinal(expr);
    //      if (variable)
    //      {
    //          if (! def_pair.da_set[variable -> LocalVariableIndex(this)])
    //          {
    //              ReportSemError(SemanticError::VARIABLE_NOT_DEFINITELY_ASSIGNED,
    //                             expr -> LeftToken(),
    //                             expr -> RightToken(),
    //                             variable -> Name());
    //              // supress further warnings
    //              def_pair.da_set.AddElement(variable -> LocalVariableIndex(this));
    //          }
    //      }
    return DefiniteBooleanExpression((expr -> resolution_opt
                                      ? expr -> resolution_opt
                                      : expr -> base), def_pair);
}

DefiniteAssignmentSet* Semantic::DefiniteCastExpression(AstExpression* expression,
                                                        DefinitePair& def_pair)
{
    AstCastExpression* expr = (AstCastExpression*) expression;
    return DefiniteBooleanExpression(expr -> expression, def_pair);
}


//
// Must have two versions, since this can be called in both expression and
// statement context.
//
void Semantic::DefiniteArrayInitializer(AstArrayInitializer* array_initializer,
                                        DefinitePair& def_pair)
{
    for (unsigned i = 0;
         i < array_initializer -> NumVariableInitializers(); i++)
    {
        AstArrayInitializer* sub_array_initializer = array_initializer ->
            VariableInitializer(i) -> ArrayInitializerCast();

        if (sub_array_initializer)
            DefiniteArrayInitializer(sub_array_initializer, def_pair);
        else
        {
            AstExpression* init =
                (AstExpression*) array_initializer -> VariableInitializer(i);
            DefiniteExpression(init, def_pair);
        }
    }
}

inline void Semantic::DefiniteArrayInitializer(AstArrayInitializer* array_initializer)
{
    DefiniteArrayInitializer(array_initializer,
                             *DefinitelyAssignedVariables());
}


inline void Semantic::DefiniteVariableInitializer(AstVariableDeclarator* variable_declarator)
{
    assert(variable_declarator -> variable_initializer_opt);
    AstExpression* init =
        variable_declarator -> variable_initializer_opt -> ExpressionCast();
    if (! init)
        DefiniteArrayInitializer((AstArrayInitializer*) variable_declarator ->
                                 variable_initializer_opt,
                                 *DefinitelyAssignedVariables());
    else
        DefiniteExpression(init, *DefinitelyAssignedVariables());

    //
    // Even when initialized by a non-constant, variables declared in a
    // switch are necessarily blank finals.
    // TODO: Sun has never given any nice official word on this.
    //
    if (DefiniteBlocks() &&
        DefiniteBlocks() -> TopBlock() -> Tag() == AstBlock::SWITCH &&
        (! init || ! init -> IsConstant()))
    {
        BlankFinals() -> AddElement(variable_declarator -> symbol ->
                                   LocalVariableIndex(this));
    }
}


inline void Semantic::DefiniteStatement(Ast* ast)
{
    (this ->* DefiniteStmt[ast -> kind])(ast);
}

inline void Semantic::DefiniteBlockStatements(AstBlock* block_body)
{
    for (unsigned i = 0; i < block_body -> NumStatements(); i++)
    {
        AstStatement* statement = block_body -> Statement(i);
        //
        // As unreachable statements already cause an error, we avoid
        // them here
        //
        if (statement -> is_reachable)
            DefiniteStatement(statement);
        else break;
    }
}


void Semantic::DefiniteBlock(Ast* stmt)
{
    AstBlock* block_body = (AstBlock*) stmt;
    unsigned i;

    DefiniteBlocks() -> Push(block_body);
    DefiniteBlockStatements(block_body);

#ifdef DUMP
    if ((control.option.g & JikesOption::VARS) &&
        block_body -> NumLocallyDefinedVariables() > 0)
    {
        Coutput << "(3) At Line "
                << lex_stream -> Line(block_body -> RightToken())
                << " the range for the following variables end:" << endl
                << endl;
        for (i = 0; i < block_body -> NumLocallyDefinedVariables(); i++)
            Coutput << "    \""
                    << block_body -> LocallyDefinedVariable(i) -> Name()
                    << "\"" << endl;
    }
#endif // DUMP
    //
    // Remove all variables that just went out of scope.
    //
    for (i = 0; i < block_body -> block_symbol -> NumVariableSymbols(); i++)
    {
        VariableSymbol* variable =
            block_body -> block_symbol -> VariableSym(i);
        int index = variable -> LocalVariableIndex(this);

        BlankFinals() -> RemoveElement(index);
        ReachableAssignments() -> RemoveElement(index);
        DefinitelyAssignedVariables() -> ReclaimElement(index);
        DefiniteBlocks() ->
            ContinuePair(DefiniteBlocks() -> Size() - 2).ReclaimElement(index);
    }

    //
    // Note that in constructing the Ast, the parser encloses each
    // labeled statement in its own block... Therefore, only blocks
    // are labeled.
    //
    if (block_body -> label_opt)
        *DefinitelyAssignedVariables() *= DefiniteBlocks() -> TopBreakPair();

    DefiniteBlocks() -> Pop();
}


void Semantic::DefiniteLocalClassStatement(Ast* stmt)
{
    AstLocalClassStatement* local_decl = (AstLocalClassStatement*) stmt;
    TypeSymbol* local_type = local_decl -> declaration -> class_body ->
        semantic_environment -> Type();
    assert(local_type -> LocalClassProcessingCompleted());
    for (unsigned i = 0; i < local_type -> NumConstructorParameters(); i++)
    {
        VariableSymbol* var =
            local_type -> ConstructorParameter(i) -> accessed_local;
        if (var -> owner == ThisMethod() &&
            (! DefinitelyAssignedVariables() ->
             da_set[var -> LocalVariableIndex(this)]))
        {
            ReportSemError(SemanticError::VARIABLE_NOT_DEFINITELY_ASSIGNED,
                           local_decl, var -> Name());
        }
    }
}


void Semantic::DefiniteLocalVariableStatement(Ast* stmt)
{
    AstLocalVariableStatement* local_decl = (AstLocalVariableStatement*) stmt;
    for (unsigned i = 0; i < local_decl -> NumVariableDeclarators(); i++)
    {
        AstVariableDeclarator* variable_declarator =
            local_decl -> VariableDeclarator(i);
        VariableSymbol* variable_symbol = variable_declarator -> symbol;
        if (! variable_symbol)
            continue;
        int index = variable_symbol -> LocalVariableIndex(this);
        if (control.option.g & JikesOption::VARS)
        {
#ifdef DUMP
            Coutput << "(3.5) Local Variable \"" << variable_symbol -> Name()
                    << " #" << index << "\" is declared at line "
                    << lex_stream -> Line(variable_declarator -> LeftToken())
                    << endl;
#endif // DUMP
            DefiniteBlocks() -> TopBlock() ->
                AddLocallyDefinedVariable(variable_symbol);
        }

        if (variable_declarator -> variable_initializer_opt)
        {
            DefiniteVariableInitializer(variable_declarator);
            DefinitelyAssignedVariables() -> AssignElement(index);
        }
        else
        {
            DefinitelyAssignedVariables() -> ReclaimElement(index);
            if (variable_symbol -> ACC_FINAL())
                BlankFinals() -> AddElement(index);
        }
    }
}


void Semantic::DefiniteExpressionStatement(Ast* stmt)
{
    AstExpressionStatement* expression_statement =
        (AstExpressionStatement*) stmt;

    DefiniteExpression(expression_statement -> expression,
                       *DefinitelyAssignedVariables());
}


void Semantic::DefiniteSynchronizedStatement(Ast* stmt)
{
    AstSynchronizedStatement* synchronized_statement =
        (AstSynchronizedStatement*) stmt;

    DefiniteExpression(synchronized_statement -> expression,
                       *DefinitelyAssignedVariables());

    DefiniteBlock(synchronized_statement -> block);
}


void Semantic::DefiniteIfStatement(Ast* stmt)
{
    AstIfStatement* if_statement = (AstIfStatement*) stmt;

    DefiniteAssignmentSet* after_expr =
        DefiniteBooleanExpression(if_statement -> expression,
                                  *DefinitelyAssignedVariables());
    DefinitePair* starting_pair =
        new DefinitePair(*DefinitelyAssignedVariables());
    if (after_expr)
        *DefinitelyAssignedVariables() = after_expr -> true_pair;

    //
    // Recall that the parser ensures that the statements that appear in an
    // if-statement (both the true and false statement) are enclosed in a
    // block.
    //
    DefiniteBlock(if_statement -> true_statement);

    if (! if_statement -> false_statement_opt) // no else part ?
    {
        *DefinitelyAssignedVariables() *= (after_expr
                                           ? after_expr -> false_pair
                                           : *starting_pair);
    }
    else
    {
        DefinitePair true_set(*DefinitelyAssignedVariables());
        *DefinitelyAssignedVariables() = (after_expr
                                          ? after_expr -> false_pair
                                          : *starting_pair);

        DefiniteBlock(if_statement -> false_statement_opt);

        *DefinitelyAssignedVariables() *= true_set;
    }

    // harmless if NULL
    delete starting_pair;
}


void Semantic::DefiniteLoopBody(BitSet& starting_set)
{
    //
    // Find the set of variables that were DU before the loop, but not DU
    // at the loop end. This requires the loop to have merged in the DU
    // status before all continue statements.
    //
    starting_set -= DefinitelyAssignedVariables() -> du_set;

    for (unsigned i = 0; i < DefiniteFinalAssignments() -> Top().Length(); i++)
    {
        AstExpression* name = DefiniteFinalAssignments() -> Top()[i];
        VariableSymbol* variable = (VariableSymbol*) name -> symbol;

        if (starting_set[variable -> LocalVariableIndex(this)])
        {
            ReportSemError(SemanticError::VARIABLE_NOT_DEFINITELY_UNASSIGNED_IN_LOOP,
                           name -> LeftToken(),
                           name -> RightToken(),
                           variable -> Name());
        }
    }

    DefiniteFinalAssignments() -> Pop();
}


void Semantic::DefiniteWhileStatement(Ast* stmt)
{
    AstWhileStatement* while_statement = (AstWhileStatement*) stmt;

    DefiniteFinalAssignments() -> Push();

    BitSet starting_set(DefinitelyAssignedVariables() -> du_set);
    DefiniteAssignmentSet* after_expr =
        DefiniteBooleanExpression(while_statement -> expression,
                                  *DefinitelyAssignedVariables());
    DefinitePair before_statement(Universe() -> Size());

    if (after_expr)
        *DefinitelyAssignedVariables() = after_expr -> true_pair;
    else before_statement = *DefinitelyAssignedVariables();

    //
    // We have already given a warning if the statement is unreachable
    //
    if (while_statement -> statement -> is_reachable)
        DefiniteBlock(while_statement -> statement);
    *DefinitelyAssignedVariables() *= DefiniteBlocks() -> TopContinuePair();
    DefiniteLoopBody(starting_set);
    *DefinitelyAssignedVariables() = DefiniteBlocks() -> TopBreakPair() *
        (after_expr ? after_expr -> false_pair : before_statement);

    delete after_expr;
}


void Semantic::DefiniteForStatement(Ast* stmt)
{
    AstForStatement* for_statement = (AstForStatement*) stmt;
    unsigned i;

    //
    // Note that in constructing the Ast, the parser encloses each
    // for-statement in its own block, so that any variables defined in the
    // for-init-statements have scope limited to the for loop. Thus, we do
    // not need to worry about declaring or reclaiming variables in the
    // for-init section in this method.
    //
    // For example, the following sequence of statements is legal:
    //
    //     for (int i = 0; i < 10; i++);
    //     for (int i = 10; i < 20; i++);
    //
    for (i = 0; i < for_statement -> NumForInitStatements(); i++)
        DefiniteStatement(for_statement -> ForInitStatement(i));

    DefiniteFinalAssignments() -> Push();

    BitSet starting_set(DefinitelyAssignedVariables() -> du_set);
    DefiniteAssignmentSet* after_end_expression = NULL;
    DefinitePair before_statement(Universe() -> Size());

    if (for_statement -> end_expression_opt)
        after_end_expression =
            DefiniteBooleanExpression(for_statement -> end_expression_opt,
                                      *DefinitelyAssignedVariables());

    if (after_end_expression)
        *DefinitelyAssignedVariables() = after_end_expression -> true_pair;
    else before_statement = *DefinitelyAssignedVariables();

    //
    // We have already given a warning if the statement is unreachable
    //
    if (for_statement -> statement -> is_reachable)
        DefiniteBlock(for_statement -> statement);

    //
    // Compute the set of variables that are definitely assigned after the
    // contained statement and after every continue statement that may exit
    // the body of the for statement.
    //
    *DefinitelyAssignedVariables() *= DefiniteBlocks() -> TopContinuePair();
    for (i = 0; i < for_statement -> NumForUpdateStatements(); i++)
        DefiniteExpressionStatement(for_statement -> ForUpdateStatement(i));
    DefiniteLoopBody(starting_set);

    //
    // Compute the set of variables that belongs to both sets below:
    //
    //    . the universe if no condition expression is present;
    //      otherwise, the set of variables that are DA when
    //      the condition expression is false.
    //
    //    . the set of variables that are DA before every
    //      break statement that may exit the for statement.
    //
    *DefinitelyAssignedVariables() = DefiniteBlocks() -> TopBreakPair() *
        (for_statement -> end_expression_opt
         ? (after_end_expression ? after_end_expression -> false_pair
            : before_statement)
         : *Universe());

    delete after_end_expression; // harmless if NULL
}


void Semantic::DefiniteForeachStatement(Ast* stmt)
{
    AstForeachStatement* for_statement = (AstForeachStatement*) stmt;

    //
    // Note that in constructing the Ast, the parser encloses each
    // for-statement in its own block, so that the loop variable defined in
    // the formal parameter has scope limited to the for loop. Thus, we do
    // not need to worry about declaring or reclaiming variables in the
    // for-init section in this method.
    //
    // For example, the following sequence of statements is legal:
    //
    //     for (int i : new int[0]);
    //     for (int i : new int[0]);
    //
    AstVariableDeclarator* variable_declarator =
        for_statement -> formal_parameter -> formal_declarator;
    VariableSymbol* variable_symbol = variable_declarator -> symbol;
    if (variable_symbol)
    {
        int index = variable_symbol -> LocalVariableIndex(this);
        if (control.option.g & JikesOption::VARS)
        {
#ifdef DUMP
            Coutput << "(3.6) Foreach Variable \"" << variable_symbol -> Name()
                    << " #" << index << "\" is declared at line "
                    << lex_stream -> Line(variable_declarator -> LeftToken())
                    << endl;
#endif // DUMP
            DefiniteBlocks() -> TopBlock() ->
                AddLocallyDefinedVariable(variable_symbol);
        }
        DefinitelyAssignedVariables() -> AssignElement(index);
    }

    DefiniteExpression(for_statement -> expression,
                       *DefinitelyAssignedVariables());
    BitSet starting_set(DefinitelyAssignedVariables() -> du_set);
    DefinitePair before_statement(*DefinitelyAssignedVariables());
    DefiniteFinalAssignments() -> Push();

    //
    // We have already given a warning if the statement is unreachable
    //
    if (for_statement -> statement -> is_reachable)
        DefiniteBlock(for_statement -> statement);

    //
    // Compute the set of variables that are definitely assigned after the
    // contained statement and after every continue statement that may exit
    // the body of the for statement.
    //
    *DefinitelyAssignedVariables() *= DefiniteBlocks() -> TopContinuePair();
    DefiniteLoopBody(starting_set);

    //
    // Compute the set of variables that are DA before every break statement
    // that may exit the for statement.
    //
    *DefinitelyAssignedVariables() =
        DefiniteBlocks() -> TopBreakPair() * before_statement;        
}


void Semantic::DefiniteDoStatement(Ast* stmt)
{
    AstDoStatement* do_statement = (AstDoStatement*) stmt;

    DefiniteFinalAssignments() -> Push();

    BitSet starting_set(DefinitelyAssignedVariables() -> du_set);

    DefiniteBlock(do_statement -> statement);

    DefinitePair after_stmt(*DefinitelyAssignedVariables());
    *DefinitelyAssignedVariables() *= DefiniteBlocks() -> TopContinuePair();
    DefiniteAssignmentSet* after_expr =
        DefiniteBooleanExpression(do_statement -> expression,
                                  *DefinitelyAssignedVariables());
    DefinitePair after_loop(Universe() -> Size());

    if (after_expr)
        *DefinitelyAssignedVariables() = after_expr -> true_pair;
    else after_loop = *DefinitelyAssignedVariables();
    DefiniteLoopBody(starting_set);

    *DefinitelyAssignedVariables() = DefiniteBlocks() -> TopBreakPair() *
        (after_expr ? after_expr -> false_pair : after_loop);

    delete after_expr;
}


void Semantic::DefiniteSwitchStatement(Ast* stmt)
{
    AstSwitchStatement* switch_statement = (AstSwitchStatement*) stmt;

    AstBlock* block_body = switch_statement -> switch_block;
    DefiniteBlocks() -> Push(block_body);

    DefiniteExpression(switch_statement -> expression,
                       *DefinitelyAssignedVariables());

    DefinitePair starting_pair(*DefinitelyAssignedVariables());

    //
    // Recall that the parser inserts an empty statement if necessary after
    // the last label, so that all SwitchBlockStatementGroups have statements.
    // The standard does not allow us to optimize for a constant switch, or
    // for enumerating all 256 byte cases with no default.
    //
    unsigned i;
    for (i = 0; i < block_body -> NumStatements(); i++)
    {
        AstSwitchBlockStatement* switch_block_statement =
            (AstSwitchBlockStatement*) block_body -> Statement(i);

        *DefinitelyAssignedVariables() *= starting_pair;
        DefiniteBlockStatements(switch_block_statement);
    }
    if (! switch_statement -> DefaultCase())
        *DefinitelyAssignedVariables() *= starting_pair;
    *DefinitelyAssignedVariables() *= DefiniteBlocks() -> TopBreakPair();

    //
    // Remove all variables that just went out of scope
    //
    for (i = 0; i < block_body -> block_symbol -> NumVariableSymbols(); i++)
    {
        VariableSymbol* variable =
            block_body -> block_symbol -> VariableSym(i);
        int index = variable -> LocalVariableIndex(this);

        BlankFinals() -> RemoveElement(index);
        ReachableAssignments() -> RemoveElement(index);
        DefinitelyAssignedVariables() -> ReclaimElement(index);
    }

    DefiniteBlocks() -> Pop();
}


void Semantic::DefiniteBreakStatement(Ast* stmt)
{
    AstBreakStatement* break_statement = (AstBreakStatement*) stmt;

    //
    // Compute the set of variables that are definitely assigned prior to
    // executing the break, including if the break occurs in a try or catch
    // block.
    //
    if (AbruptFinallyStack().Top() < break_statement -> nesting_level)
    {
        DefiniteBlocks() -> BreakPair(break_statement -> nesting_level) *=
            *DefinitelyAssignedVariables();
    }

    //
    // After execution of a break statement, it is vacuously true
    // that every variable has definitely been assigned and no final
    // variable has been possibly assigned (as nothing is reachable
    // any way).
    //
    *DefinitelyAssignedVariables() = *Universe();
}


void Semantic::DefiniteContinueStatement(Ast* stmt)
{
    AstContinueStatement* continue_statement = (AstContinueStatement*) stmt;

    //
    // Compute the set of variables that are definitely assigned prior to
    // executing the continue, including if the continue occurs in a try or
    // catch block.
    //
    if (AbruptFinallyStack().Top() < continue_statement -> nesting_level)
    {
        DefiniteBlocks() -> ContinuePair(continue_statement ->
                                         nesting_level) *=
            *DefinitelyAssignedVariables();
    }

    //
    // After execution of a continue statement, it is vacuously true
    // that every variable has definitely been assigned and no final
    // variable has been possibly assigned (as nothing is reachable
    // any way).
    //
    *DefinitelyAssignedVariables() = *Universe();
}


void Semantic::DefiniteReturnStatement(Ast* stmt)
{
    AstReturnStatement* return_statement = (AstReturnStatement*) stmt;

    if (return_statement -> expression_opt)
        DefiniteExpression(return_statement -> expression_opt,
                           *DefinitelyAssignedVariables());

    if (AbruptFinallyStack().Top() == 0)
        DefiniteBlocks() -> ReturnPair() *= *DefinitelyAssignedVariables();

    //
    // After execution of a return statement, it is vacuously true
    // that every variable has definitely been assigned and no final
    // variable has been possibly assigned (as nothing is reachable
    // any way).
    //
    *DefinitelyAssignedVariables() = *Universe();
}


void Semantic::DefiniteThrowStatement(Ast* stmt)
{
    AstThrowStatement* throw_statement = (AstThrowStatement*) stmt;

    DefiniteExpression(throw_statement -> expression,
                       *DefinitelyAssignedVariables());

    //
    // After execution of a throw statement, it is vacuously true
    // that every variable has definitely been assigned and no final
    // variable has been possibly assigned (as nothing is reachable
    // any way).
    //
    *DefinitelyAssignedVariables() = *Universe();
}


void Semantic::DefiniteTryStatement(Ast* stmt)
{
    AstTryStatement* try_statement = (AstTryStatement*) stmt;
    if (try_statement -> finally_clause_opt &&
        (! try_statement -> finally_clause_opt -> block ->
         can_complete_normally))
    {
        AbruptFinallyStack().Push(try_statement -> finally_clause_opt ->
                                  block -> nesting_level);
    }

    DefinitePair starting_pair(*DefinitelyAssignedVariables());
    BitSet already_assigned(*ReachableAssignments());
    ReachableAssignments() -> SetEmpty();

    DefiniteBlock(try_statement -> block);

    BitSet before_catch_finals(starting_pair.du_set - *ReachableAssignments()),
           possibly_finals_union(DefinitelyAssignedVariables() -> du_set);
    //
    // We initialize the variable after_blocks here. It is used to calculate
    // intersection of the set of variables that are definitely assigned by
    // all the blocks: the try block, all the catch blocks, if any, and the
    // finally block, if there is one.
    //
    BitSet after_blocks(DefinitelyAssignedVariables() -> da_set);

    //
    // Recall that the body of the catch blocks must not be
    // processed within the environment of the associated try whose
    // exceptions they are supposed to catch but within the immediate
    // enclosing block (which may itself be a try block).
    //
    for (unsigned i = 0; i < try_statement -> NumCatchClauses(); i++)
    {
        DefinitelyAssignedVariables() -> da_set = starting_pair.da_set;
        DefinitelyAssignedVariables() -> du_set = before_catch_finals;
        AstCatchClause* clause = try_statement -> CatchClause(i);

        //
        // The catch clause parameter must be added, in case it is final.
        // It is already initialized.
        //
        VariableSymbol* variable = clause -> parameter_symbol;
        int index = variable -> LocalVariableIndex(this);
        DefinitelyAssignedVariables() -> AddElement(index);
        if (control.option.g & JikesOption::VARS)
        {
#ifdef DUMP
            Coutput << "(7) Variable \"" << variable -> Name() << " #"
                    << index << "\" is defined at line "
                    << lex_stream -> Line(clause -> formal_parameter -> LeftToken())
                    << endl;
#endif // DUMP
        }
        DefiniteBlock(clause -> block);

        //
        // The parameter goes out of scope. We do not need to remove it from
        // reachable assignments, since if it was final, it can't be assigned.
        //
        DefinitelyAssignedVariables() -> ReclaimElement(index);
#ifdef DUMP
        VariableSymbol* variable = clause -> parameter_symbol;
        if (control.option.g & JikesOption::VARS)
            Coutput << "(8) Variable \"" << variable -> Name() << " #"
                    << index << "\" goes out of scope at line "
                    << lex_stream -> Line(clause -> formal_parameter -> RightToken())
                    << endl;
#endif // DUMP

        //
        // Process the set of variables that were definitely assigned
        // after this catch block
        //
        possibly_finals_union *= DefinitelyAssignedVariables() -> du_set;
        after_blocks *= DefinitelyAssignedVariables() -> da_set;
    }

    //
    // Like the catch clauses, a finally block must not be processed
    // in the environment of its associated try block but in the
    // environment of its immediate enclosing block.
    //
    if (try_statement -> finally_clause_opt)
    {
        if (! try_statement -> finally_clause_opt -> block ->
            can_complete_normally)
        {
            AbruptFinallyStack().Pop();
        }
        DefinitelyAssignedVariables() -> da_set = starting_pair.da_set;
        DefinitelyAssignedVariables() -> du_set =
            starting_pair.du_set - *ReachableAssignments();
        DefiniteBlock(try_statement -> finally_clause_opt -> block);
        DefinitelyAssignedVariables() -> da_set += after_blocks;
    }
    else
    {
        DefinitelyAssignedVariables() -> da_set = after_blocks;
        DefinitelyAssignedVariables() -> du_set = possibly_finals_union;
    }
    *ReachableAssignments() += already_assigned;
}


void Semantic::DefiniteAssertStatement(Ast* stmt)
{
    AstAssertStatement* assert_statement = (AstAssertStatement*) stmt;

    //
    // Remember what variables were assigned beforehand.
    //
    DefinitePair before_assert(*DefinitelyAssignedVariables());
    DefiniteAssignmentSet* after_condition =
        DefiniteBooleanExpression(assert_statement -> condition,
                                  *DefinitelyAssignedVariables());

    if (after_condition)
    {
        //
        // The second expression is evaluated only when the first is false
        // Don't modify da, but update du, as a variable is DU after the assert
        // iff it is DU before the assert and DU after the condition when true.
        //
        *DefinitelyAssignedVariables() = after_condition -> false_pair;
        before_assert.du_set *= after_condition -> true_pair.du_set;
    }
    else before_assert.du_set *= DefinitelyAssignedVariables() -> du_set;

    if (assert_statement -> message_opt)
        DefiniteExpression(assert_statement -> message_opt,
                           *DefinitelyAssignedVariables());

    //
    // Restore definitely assigned variables to what they were before,
    // since asserts may be disabled
    //
    *DefinitelyAssignedVariables() = before_assert;

    // harmless if NULL
    delete after_condition;
}


//
// Called only from DefiniteConstructorBody, for this() calls.
//
void Semantic::DefiniteThisCall(AstThisCall* this_call)
{
    for (unsigned i = 0; i < this_call -> arguments -> NumArguments(); i++)
        DefiniteExpression(this_call -> arguments -> Argument(i),
                           *DefinitelyAssignedVariables());
}


//
// Called only from DefiniteConstructorBody, for super() calls.
//
void Semantic::DefiniteSuperCall(AstSuperCall* super_call)
{
    if (super_call -> base_opt)
        DefiniteExpression(super_call -> base_opt,
                           *DefinitelyAssignedVariables());
    for (unsigned i = 0; i < super_call -> arguments -> NumArguments(); i++)
        DefiniteExpression(super_call -> arguments -> Argument(i),
                           *DefinitelyAssignedVariables());
}


void Semantic::DefiniteMethodBody(AstMethodDeclaration* method_declaration)
{
    unsigned i;
    assert(FinalFields());
    AstBlock* block_body = method_declaration -> method_body_opt;
    if (! block_body)
        return;

#ifdef DUMP
    if (control.option.g & JikesOption::VARS)
        Coutput << "(9) Processing method \""
                << method_declaration -> method_symbol -> Name() << "\" in "
                << ThisType() -> ContainingPackageName()
                << "/" << ThisType() -> ExternalName() << endl;
#endif // DUMP
    int size = block_body -> block_symbol -> max_variable_index +
        FinalFields() -> Length();
    Universe() -> Resize(size, BitSet::UNIVERSE);
    int stack_size = method_declaration -> method_symbol -> max_block_depth;
    DefiniteBlocks() = new DefiniteBlockStack(stack_size, size);
    DefinitelyAssignedVariables() -> Resize(size);
    BlankFinals() -> Resize(size, BitSet::EMPTY);
    ReachableAssignments() -> Resize(size, BitSet::EMPTY);

    DefiniteBlocks() -> Push(block_body);

    AstMethodDeclarator* method_declarator =
        method_declaration -> method_declarator;
    for (i = 0; i < method_declarator -> NumFormalParameters(); i++)
    {
        AstVariableDeclarator* formal_declarator =
            method_declarator -> FormalParameter(i) -> formal_declarator;
        DefinitelyAssignedVariables() ->
            AssignElement(formal_declarator -> symbol ->
                          LocalVariableIndex(this));
#ifdef DUMP
        if (control.option.g & JikesOption::VARS)
        {
            VariableSymbol* variable = formal_declarator -> symbol;
            Coutput << "(10) Variable \"" << variable -> Name() << " #"
                    << variable -> LocalVariableIndex(this)
                    << "\" is defined at line "
                    << lex_stream -> Line(formal_declarator -> LeftToken())
                    << endl;
        }
#endif // DUMP
    }

    DefiniteBlockStatements(block_body);

#ifdef DUMP
    if ((control.option.g & JikesOption::VARS) &&
        block_body -> NumLocallyDefinedVariables() > 0)
    {
        Coutput << "(11) At Line "
                << lex_stream -> Line(block_body -> RightToken())
                << " the range for the following variables end:" << endl
                << endl;
        for (i = 0; i < block_body -> NumLocallyDefinedVariables(); i++)
            Coutput << "    \""
                    << block_body -> LocallyDefinedVariable(i) -> Name()
                    << "\"" << endl;
    }
#endif // DUMP
    DefiniteBlocks() -> Pop();

    delete DefiniteBlocks();
    DefiniteBlocks() = NULL;
    size = FinalFields() -> Length();
    Universe() -> Resize(size);
    DefinitelyAssignedVariables() -> Resize(size);
    BlankFinals() -> Resize(size);
    ReachableAssignments() -> Resize(size);
}


void Semantic::DefiniteConstructorBody(AstConstructorDeclaration* constructor_declaration)
{
    unsigned i;
    assert(FinalFields());
#ifdef DUMP
    if (control.option.g & JikesOption::VARS)
        Coutput << "(12) Processing constructor \""
                << constructor_declaration -> constructor_symbol -> Name()
                << "\" in "
                << ThisType() -> ContainingPackageName() << "/"
                << ThisType() -> ExternalName() << endl;
#endif // DUMP
    AstMethodBody* block_body = constructor_declaration -> constructor_body;

    int size = block_body -> block_symbol -> max_variable_index +
        FinalFields() -> Length();
    Universe() -> Resize(size, BitSet::UNIVERSE);
    int stack_size =
        constructor_declaration -> constructor_symbol -> max_block_depth;
    DefiniteBlocks() = new DefiniteBlockStack(stack_size, size);
    DefinitelyAssignedVariables() -> Resize(size);
    BlankFinals() -> Resize(size, BitSet::EMPTY);
    ReachableAssignments() -> Resize(size, BitSet::EMPTY);

    DefiniteBlocks() -> Push(block_body);

    AstMethodDeclarator* constructor_declarator =
        constructor_declaration -> constructor_declarator;
    for (i = 0; i < constructor_declarator -> NumFormalParameters(); i++)
    {
        AstVariableDeclarator* formal_declarator =
            constructor_declarator -> FormalParameter(i) -> formal_declarator;
        DefinitelyAssignedVariables() ->
            AddElement(formal_declarator -> symbol -> LocalVariableIndex(this));
#ifdef DUMP
        if (control.option.g & JikesOption::VARS)
        {
            VariableSymbol* variable = formal_declarator -> symbol;
            Coutput << "(13) Variable \"" << variable -> Name() << " #"
                    << variable -> LocalVariableIndex(this)
                    << "\" is defined at line "
                    << lex_stream -> Line(formal_declarator -> LeftToken())
                    << endl;
        }
#endif // DUMP
    }

    if (block_body -> explicit_constructor_opt)
    {
        if (block_body -> explicit_constructor_opt -> ThisCallCast())
            DefiniteThisCall((AstThisCall*) block_body ->
                             explicit_constructor_opt);
        else DefiniteSuperCall((AstSuperCall*) block_body ->
                               explicit_constructor_opt);
    }
    DefiniteBlockStatements(block_body);

#ifdef DUMP
    if ((control.option.g & JikesOption::VARS) &&
        block_body -> NumLocallyDefinedVariables() > 0)
    {
        Coutput << "(14) At Line "
                << lex_stream -> Line(block_body -> RightToken())
                << " the range for the following variables end:" << endl
                << endl;
        for (unsigned j = 0; j < block_body -> NumLocallyDefinedVariables(); j++)
            Coutput << "    \""
                    << block_body -> LocallyDefinedVariable(j) -> Name()
                    << "\"" << endl;
    }
#endif // DUMP
    //
    // Compute the set of finals that has definitely been assigned in this
    // constructor.
    //
    *DefinitelyAssignedVariables() *= DefiniteBlocks() -> ReturnPair();
    DefiniteBlocks() -> Pop();

    delete DefiniteBlocks();
    DefiniteBlocks() = NULL;
    size = FinalFields() -> Length();
    Universe() -> Resize(size);
    DefinitelyAssignedVariables() -> Resize(size);
    BlankFinals() -> Resize(size);
    ReachableAssignments() -> Resize(size);
}


void Semantic::DefiniteBlockInitializer(AstBlock* block_body, int stack_size)
{
    assert(FinalFields());
#ifdef DUMP
    if (control.option.g & JikesOption::VARS)
        Coutput << "(15) Processing Initializer block in "
                << ThisType() -> ContainingPackageName() << "/"
                << ThisType() -> ExternalName() << endl;
#endif // DUMP
    int size = block_body -> block_symbol -> max_variable_index +
        FinalFields() -> Length();
    Universe() -> Resize(size, BitSet::UNIVERSE);
    DefiniteBlocks() = new DefiniteBlockStack(stack_size, size);
    DefinitelyAssignedVariables() -> Resize(size);
    BlankFinals() -> Resize(size, BitSet::EMPTY);
    ReachableAssignments() -> Resize(size, BitSet::EMPTY);

    DefiniteBlocks() -> Push(block_body);
    DefiniteBlockStatements(block_body);

#ifdef DUMP
    if ((control.option.g & JikesOption::VARS) &&
        block_body -> NumLocallyDefinedVariables() > 0)
    {
        Coutput << "(16) At Line "
                << lex_stream -> Line(block_body -> RightToken())
                << " the range for the following variables end:" << endl
                << endl;
        for (i = 0; i < block_body -> NumLocallyDefinedVariables(); i++)
            Coutput << "    \""
                    << block_body -> LocallyDefinedVariable(i) -> Name()
                    << "\"" << endl;
    }
#endif // DUMP
    DefiniteBlocks() -> Pop();

    delete DefiniteBlocks();
    DefiniteBlocks() = NULL;
    size = FinalFields() -> Length();
    Universe() -> Resize(size);
    DefinitelyAssignedVariables() -> Resize(size);
    BlankFinals() -> Resize(size);
    ReachableAssignments() -> Resize(size);
}


void Semantic::DefiniteFieldInitializer(AstVariableDeclarator* variable_declarator)
{
    assert(FinalFields());

    DefiniteVariableInitializer(variable_declarator);
    if (variable_declarator -> symbol -> ACC_FINAL())
    {
        DefinitelyAssignedVariables() ->
            AssignElement(variable_declarator -> symbol ->
                          LocalVariableIndex());
    }
}


void Semantic::DefiniteSetup()
{
    //
    // Compute the set of final variables (all fields in an interface are
    // final) in this type. Then process all initializers.
    //
    assert(! FinalFields());
    TypeSymbol* this_type = ThisType();
    FinalFields() =
        new Tuple<VariableSymbol*> (this_type -> NumVariableSymbols());
    int size = 0;
    for (unsigned i = 0; i < this_type -> NumVariableSymbols(); i++)
    {
        VariableSymbol* variable_symbol = this_type -> VariableSym(i);
        if (variable_symbol -> ACC_FINAL() &&
            ! variable_symbol -> ACC_SYNTHETIC())
        {
            variable_symbol -> SetLocalVariableIndex(size++);
            FinalFields() -> Next() = variable_symbol;
        }
    }
    Universe() = new DefinitePair(size, BitSet::UNIVERSE);
    DefiniteFinalAssignments() = new DefiniteFinalAssignmentStack();
    DefinitelyAssignedVariables() = new DefinitePair(size);
    BlankFinals() = new BitSet(size, BitSet::EMPTY);
    ReachableAssignments() = new BitSet(size, BitSet::EMPTY);
    for (int j = 0; j < size; j++)
    {
        VariableSymbol* final_var = (*FinalFields())[j];
        if (! final_var -> declarator -> variable_initializer_opt)
            BlankFinals() -> AddElement(j);
    }
}


void Semantic::DefiniteCleanUp()
{
    assert (FinalFields());
    delete FinalFields();
    FinalFields() = NULL;
    delete Universe();
    delete DefinitelyAssignedVariables();
    delete DefiniteFinalAssignments();
    delete BlankFinals();
    delete ReachableAssignments();
}

#ifdef HAVE_JIKES_NAMESPACE
} // Close namespace Jikes block
#endif

Generated by  Doxygen 1.6.0   Back to index