Ejemplo 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;
}
Ejemplo n.º 2
0
symbolt &cpp_declarator_convertert::convert(
    const typet &declaration_type,
    const cpp_storage_spect &storage_spec,
    const cpp_member_spect &member_spec,
    cpp_declaratort &declarator)
{
    assert(declaration_type.is_not_nil());

    if(declaration_type.id()=="cpp-cast-operator")
    {
        typet type;
        type.swap(declarator.name().get_sub().back());
        declarator.type().subtype()=type;
        std::string tmp;
        cpp_typecheck.typecheck_type(type);
        irept name(ID_name);
        name.set(ID_identifier, "("+cpp_type2name(type)+")");
        declarator.name().get_sub().back().swap(name);
    }

    assert(declarator.id()==ID_cpp_declarator);
    final_type=declarator.merge_type(declaration_type);
    assert(final_type.is_not_nil());

    cpp_template_args_non_tct template_args;

    // run resolver on scope
    {
        cpp_save_scopet save_scope(cpp_typecheck.cpp_scopes);

        cpp_typecheck_resolvet cpp_typecheck_resolve(cpp_typecheck);

        cpp_typecheck_resolve.resolve_scope(
            declarator.name(), base_name, template_args);

        scope=&cpp_typecheck.cpp_scopes.current_scope();

        // check the declarator-part of the type, in that scope
        cpp_typecheck.typecheck_type(final_type);
    }

    is_code=is_code_type(final_type);

    // global-scope arrays must have fixed size
    if(scope->is_global_scope())
        cpp_typecheck.check_fixed_size_array(final_type);

    get_final_identifier();

    // first see if it is a member
    if(scope->id_class==cpp_idt::CLASS && !is_friend)
    {
        // it's a member! it must be declared already

        typet &method_qualifier=
            static_cast<typet &>(declarator.method_qualifier());

        // adjust template type
        if(final_type.id()==ID_template)
        {
            assert(0);
            typet tmp;
            tmp.swap(final_type.subtype());
            final_type.swap(tmp);
        }

        // try static first
        symbol_tablet::symbolst::iterator c_it=
            cpp_typecheck.symbol_table.symbols.find(final_identifier);

        if(c_it==cpp_typecheck.symbol_table.symbols.end())
        {
            // adjust type if it's a non-static member function
            if(final_type.id()==ID_code)
                cpp_typecheck.adjust_method_type(
                    scope->identifier, final_type, method_qualifier);

            get_final_identifier();

            // try again
            c_it=cpp_typecheck.symbol_table.symbols.find(final_identifier);

            if(c_it==cpp_typecheck.symbol_table.symbols.end())
            {
                cpp_typecheck.err_location(declarator.name());
                cpp_typecheck.str << "member `" << base_name
                                  << "' not found in scope `"
                                  << scope->identifier << "'";
                throw 0;
            }
        }

        assert(c_it!=cpp_typecheck.symbol_table.symbols.end());

        symbolt &symbol=c_it->second;

        combine_types(declarator.name().source_location(), final_type, symbol);
        enforce_rules(symbol);

        // If it is a constructor, we take care of the
        // object initialization
        if(final_type.get(ID_return_type)==ID_constructor)
        {
            const cpp_namet &name=declarator.name();

            exprt symbol_expr=
                cpp_typecheck.resolve(
                    name,
                    cpp_typecheck_resolvet::TYPE,
                    cpp_typecheck_fargst());

            if(symbol_expr.id()!=ID_type ||
                    symbol_expr.type().id()!=ID_symbol)
            {
                cpp_typecheck.err_location(name.source_location());
                cpp_typecheck.str << "error: expected type";
                throw 0;
            }

            irep_idt identifier=symbol_expr.type().get(ID_identifier);
            const symbolt &symb=cpp_typecheck.lookup(identifier);
            const typet &type = symb.type;
            assert(type.id()==ID_struct);

            if(declarator.find(ID_member_initializers).is_nil())
                declarator.set(ID_member_initializers, ID_member_initializers);

            cpp_typecheck.check_member_initializers(
                type.find(ID_bases),
                to_struct_type(type).components(),
                declarator.member_initializers());

            cpp_typecheck.full_member_initialization(
                to_struct_type(type),
                declarator.member_initializers());
        }

        if(!storage_spec.is_extern())
            symbol.is_extern=false;

        // initializer?
        handle_initializer(symbol, declarator);

        return symbol;
    }
    else
    {
        // no, it's no way a method

        // we won't allow the constructor/destructor type
        if(final_type.id()==ID_code &&
                to_code_type(final_type).return_type().id()==ID_constructor)
        {
            cpp_typecheck.err_location(declarator.name().source_location());
            cpp_typecheck.str << "function must have return type";
            throw 0;
        }

        // already there?
        symbol_tablet::symbolst::iterator c_it=
            cpp_typecheck.symbol_table.symbols.find(final_identifier);

        if(c_it==cpp_typecheck.symbol_table.symbols.end())
            return convert_new_symbol(storage_spec, member_spec, declarator);

        symbolt &symbol=c_it->second;

        if(!storage_spec.is_extern())
            symbol.is_extern = false;

        if(declarator.get_bool("#template_case"))
            return symbol;

        combine_types(declarator.name().source_location(), final_type, symbol);
        enforce_rules(symbol);

        // initializer?
        handle_initializer(symbol, declarator);

        if(symbol.type.id()=="cpp-template-type")
        {
            cpp_scopet::id_sett id_set;

            scope->lookup_identifier(symbol.name, cpp_idt::TEMPLATE_PARAMETER, id_set);

            if(id_set.empty())
            {
                cpp_idt &identifier=
                    cpp_typecheck.cpp_scopes.put_into_scope(symbol,*scope);
                identifier.id_class=cpp_idt::TEMPLATE_PARAMETER;
            }
        }

        return symbol;
    }
}
Ejemplo n.º 3
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().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;
}