Beispiel #1
0
VarDecl *
NameResolver::HandleVarDecl(NameToken name, TypeSpecifier &spec, Expression *init)
{
  Scope *scope = getOrCreateScope();

  // :TODO: set variadic info
  VarDecl *var = new (pool_) VarDecl(name, init);

  // Note: the parser has already bound |var->init()| at this point, meaning
  // that aside from globals it should be impossible to self-initialize like:
  //    int x = x;
  //
  // :TODO: do check this for globals.
  VariableSymbol *sym = new (pool_) VariableSymbol(var, scope, var->name());
  registerSymbol(sym);
  var->setSymbol(sym);

  // Set this before we evaluate the type, since it determines whether or not
  // a const on a parameter is meaningless.
  if (spec.isByRef()) {
    assert(scope->kind() == Scope::Argument && sym->isArgument());
    sym->storage_flags() |= StorageFlags::byref;
  }

  // See the comment in TypeResolver::visitVarDecl for why we do not want to
  // infer sizes from literals for arguments.
  if (init &&
      !scope->isArgument() &&
      ((init->isArrayLiteral() && init->asArrayLiteral()->isFixedArrayLiteral()) ||
       (init->isStringLiteral())))
  {
    // Wait until the type resolution pass to figure this out. We still have
    // to precompute the base though.
    if (Type *type = resolveBase(spec))
      spec.setResolvedBaseType(type);
    var->te() = TypeExpr(new (pool_) TypeSpecifier(spec));
  } else {
    VarDeclSpecHelper helper(var, nullptr);
    var->te() = resolve(spec, &helper);
  }

  if (var->te().resolved()) {
    sym->setType(var->te().resolved());

    // We need to check this both here and in lazy resolution, which is gross,
    // but I don't see any obvious way to simplify it yet.
    if (spec.isByRef() && sym->type()->passesByReference()) {
      cc_.report(spec.byRefLoc(), rmsg::type_cannot_be_ref)
        << sym->type();
    }
  }

  // Even if we were able to resolve the type, if we have to resolve a constant
  // value, we'll have to add it to the resolver queue.
  if (!var->te().resolved() || sym->canUseInConstExpr())
    tr_.addPending(var);

  return var;
}
bool
VarDeclSpecHelper::receiveConstQualifier(CompileContext &cc, const SourceLocation &constLoc, Type *type)
{
  VariableSymbol *sym = decl_->sym();
  if (sym->isArgument()) {
    if (!!(sym->storage_flags() & StorageFlags::byref)) {
      cc.report(constLoc, rmsg::const_ref_has_no_meaning) << type;
      return true;
    }
    if (!type->passesByReference()) {
      cc.report(constLoc, rmsg::const_has_no_meaning) << type;
      return true;
    }
  } else if (TypeSupportsCompileTimeInterning(type)) {
    sym->storage_flags() |= StorageFlags::constval;
  }

  sym->storage_flags() |= StorageFlags::readonly;
  return true;
}