Esempio n. 1
0
symbolt &cpp_declarator_convertert::convert_new_symbol(
    const cpp_storage_spect &storage_spec,
    const cpp_member_spect &member_spec,
    cpp_declaratort &declarator)
{
    irep_idt pretty_name=get_pretty_name();

    symbolt symbol;

    symbol.name=final_identifier;
    symbol.base_name=base_name;
    symbol.value=declarator.value();
    symbol.location=declarator.name().source_location();
    symbol.mode=linkage_spec==ID_auto?ID_cpp:linkage_spec;
    symbol.module=cpp_typecheck.module;
    symbol.type=final_type;
    symbol.is_type=is_typedef;
    symbol.is_macro=is_typedef && !is_template_parameter;
    symbol.pretty_name=pretty_name;

    // Constant? These are propagated.
    if(symbol.type.get_bool(ID_C_constant) &&
            symbol.value.is_not_nil())
        symbol.is_macro=true;

    if(member_spec.is_inline())
        symbol.type.set(ID_C_inlined, true);

    if(!symbol.is_type)
    {
        if(is_code)
        {
            // it is a function
            if(storage_spec.is_static())
                symbol.is_file_local=true;
        }
        else
        {
            // it is a variable
            symbol.is_state_var=true;
            symbol.is_lvalue = !is_reference(symbol.type) &&
                               !(symbol.type.get_bool(ID_C_constant) &&
                                 is_number(symbol.type) &&
                                 symbol.value.id() == ID_constant);

            if(cpp_typecheck.cpp_scopes.current_scope().is_global_scope())
            {
                symbol.is_static_lifetime=true;

                if(storage_spec.is_extern())
                    symbol.is_extern=true;
            }
            else
            {
                if(storage_spec.is_static())
                {
                    symbol.is_static_lifetime=true;
                    symbol.is_file_local=true;
                }
                else if(storage_spec.is_extern())
                {
                    cpp_typecheck.err_location(storage_spec);
                    throw "external storage not permitted here";
                }
            }
        }
    }

    if(symbol.is_static_lifetime)
        cpp_typecheck.dynamic_initializations.push_back(symbol.name);

    // move early, it must be visible before doing any value
    symbolt *new_symbol;

    if(cpp_typecheck.symbol_table.move(symbol, new_symbol))
        throw "cpp_typecheckt::convert_declarator: symbol_table.move() failed";

    if(!is_code)
    {
        cpp_scopest::id_sett id_set;

        cpp_typecheck.cpp_scopes.current_scope().lookup(
            base_name, cpp_scopet::SCOPE_ONLY, id_set);

        for(cpp_scopest::id_sett::const_iterator
                id_it=id_set.begin();
                id_it!=id_set.end();
                id_it++)
        {
            const cpp_idt &id=**id_it;
            // the name is already in the scope
            // this is ok if they belong to different categories

            if(!id.is_class() && !id.is_enum())
            {
                cpp_typecheck.err_location(new_symbol->location);
                cpp_typecheck.str << "`" << base_name << "' already in scope";
                throw 0;
            }
        }
    }

    // put into scope
    cpp_idt &identifier=
        cpp_typecheck.cpp_scopes.put_into_scope(*new_symbol, *scope, is_friend);

    if(is_template)
        identifier.id_class=cpp_idt::TEMPLATE;
    else if(is_template_parameter)
        identifier.id_class=cpp_idt::TEMPLATE_PARAMETER;
    else if(is_typedef)
        identifier.id_class=cpp_idt::TYPEDEF;
    else
        identifier.id_class=cpp_idt::SYMBOL;

    // do the value
    if(!new_symbol->is_type)
    {
        if(is_code && declarator.type().id()!=ID_template)
            cpp_typecheck.add_function_body(new_symbol);

        if(!is_code)
            cpp_typecheck.convert_initializer(*new_symbol);
    }

    enforce_rules(*new_symbol);

    return *new_symbol;
}
symbolt &cpp_declarator_convertert::convert_new_symbol(
    const cpp_storage_spect &storage_spec,
    const cpp_member_spect &member_spec,
    cpp_declaratort &declarator)
{
    irep_idt pretty_name=get_pretty_name();

    symbolt symbol;

    symbol.name=final_identifier;
    symbol.base_name=base_name;
    symbol.value=declarator.value();
    symbol.location=declarator.name().location();
    symbol.mode=mode;
    symbol.module=cpp_typecheck.module;
    symbol.type=final_type;
    symbol.is_type=is_typedef;
    symbol.is_macro=is_typedef && !is_template_argument;
    symbol.pretty_name=pretty_name;
    symbol.mode=cpp_typecheck.current_mode;

    // We always insert throw_decl to the begin of the function
    if(declarator.throw_decl().statement()=="throw_decl")
    {
        symbol.value.operands().insert(
            symbol.value.operands().begin(),
            declarator.throw_decl());

        // Insert flag to end of constructor
        // so we know when to remove throw_decl
        symbol.value.operands().push_back(
            codet("throw_decl_end"));
    }

    // Constant? These are propagated.
    if(symbol.type.cmt_constant() &&
            symbol.value.is_not_nil())
        symbol.is_macro=true;

    if(member_spec.is_inline())
        symbol.type.set("#inlined", true);

    if(!symbol.is_type)
    {
        if(!is_code)
        {
            // it is a variable
            symbol.is_statevar=true;
            symbol.lvalue = !is_reference(symbol.type) &&
                            !(symbol.type.cmt_constant() &&
                              is_number(symbol.type) &&
                              symbol.value.id() == "constant");

            if(cpp_typecheck.cpp_scopes.current_scope().is_global_scope())
            {
                symbol.static_lifetime=true;

                if(storage_spec.is_extern())
                    symbol.is_extern=true;
            }
            else
            {
                if(storage_spec.is_static())
                {
                    //symbol.static_lifetime=true;
                    symbol.file_local=true;
                }
                else if(storage_spec.is_extern())
                {
                    cpp_typecheck.err_location(storage_spec);
                    throw "external storage not permitted here";
                }
            }
        }
    }

    if(symbol.static_lifetime)
        cpp_typecheck.dinis.push_back(symbol.name);

    // move early, it must be visible before doing any value
    symbolt *new_symbol;

    if(cpp_typecheck.context.move(symbol, new_symbol))
        throw "cpp_typecheckt::convert_declarator: context.move() failed";

    if(!is_code)
    {
        cpp_scopest::id_sett id_set;

        cpp_typecheck.cpp_scopes.current_scope().lookup(
            base_name, cpp_scopet::SYMBOL, id_set);

        for(cpp_scopest::id_sett::const_iterator
                id_it=id_set.begin();
                id_it!=id_set.end();
                id_it++)
        {
            const cpp_idt &id=**id_it;
            // the name is already in the scope
            // this is ok if they belong to different categories

            if(!id.is_class() && !id.is_enum())
            {
                cpp_typecheck.err_location(new_symbol->location);
                cpp_typecheck.str << "`" << base_name << "' already in scope";
                throw 0;
            }
        }
    }

    // put into scope
    cpp_idt &identifier=
        cpp_typecheck.cpp_scopes.put_into_scope(*new_symbol, *scope, is_friend);

    if(is_template)
        identifier.id_class=cpp_idt::TEMPLATE;
    else if(is_template_argument)
        identifier.id_class=cpp_idt::TEMPLATE_ARGUMENT;
    else if(is_typedef)
        identifier.id_class=cpp_idt::TYPEDEF;
    else
        identifier.id_class=cpp_idt::SYMBOL;

    // do the value
    if(!new_symbol->is_type)
    {
        if(is_code && declarator.type().id()!="template")
            cpp_typecheck.add_function_body(new_symbol);

        if(!is_code && !declarator.find("name").get_bool("catch_decl"))
            cpp_typecheck.convert_initializer(*new_symbol);
    }

    enforce_rules(*new_symbol);

    return *new_symbol;
}