Пример #1
0
C2::ExprResult C2Sema::ActOnTypeQualifier(ExprResult R, unsigned qualifier) {
    assert(R.get());
    if (qualifier) {
#ifdef SEMA_DEBUG
        std::cerr << COL_SEMA << "SEMA: Qualifier Type" << ANSI_NORMAL"\n";
#endif
        TypeExpr* typeExpr = cast<TypeExpr>(R.get());
        // TODO use typeExpr.addConst() and just return QualType (not ref) in getType()
        QualType qt = typeExpr->getType();
        if (qualifier & TYPE_CONST) qt.addConst();
        if (qualifier & TYPE_VOLATILE) qt.addVolatile();
        if (qualifier & TYPE_LOCAL) typeExpr->setLocalQualifier();
        typeExpr->setType(qt);
    }
    return R;
}
Пример #2
0
QualType TypeResolver::resolveUnresolved(QualType Q) const {
    const Type* T = Q.getTypePtr();
    switch (Q->getTypeClass()) {
    case TC_BUILTIN:
        return Q;
    case TC_POINTER:
        {
            // Dont return new type if not needed
            const PointerType* P = cast<PointerType>(T);
            QualType t1 = P->getPointeeType();
            QualType Result = resolveUnresolved(t1);
            if (t1 == Result) return Q;
            // TODO qualifiers
            return typeContext.getPointerType(Result);
        }
    case TC_ARRAY:
        {
            const ArrayType* A = cast<ArrayType>(T);
            QualType t1 = A->getElementType();
            QualType Result = resolveUnresolved(t1);
            if (t1 == Result) return Q;
            // TODO qualifiers
            return typeContext.getArrayType(Result, A->getSizeExpr(), false, A->isIncremental());

        }
    case TC_UNRESOLVED:
        {
            const UnresolvedType* U = cast<UnresolvedType>(T);
            TypeDecl* TD = U->getDecl();
            assert(TD);
            QualType result = TD->getType();
            if (Q.isConstQualified()) result.addConst();
            if (Q.isVolatileQualified()) result.addVolatile();
            return result;
        }
    case TC_ALIAS:
    case TC_STRUCT:
    case TC_ENUM:
    case TC_FUNCTION:
        return Q;
    case TC_MODULE:
        assert(0 && "TBD");
        return Q;
    }
    return Q;
}
Пример #3
0
Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
                                      TypeSourceInfo *EncodedTypeInfo,
                                      SourceLocation RParenLoc) {
  QualType EncodedType = EncodedTypeInfo->getType();
  QualType StrTy;
  if (EncodedType->isDependentType())
    StrTy = Context.DependentTy;
  else {
    std::string Str;
    Context.getObjCEncodingForType(EncodedType, Str);

    // The type of @encode is the same as the type of the corresponding string,
    // which is an array type.
    StrTy = Context.CharTy;
    // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
    if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings)
      StrTy.addConst();
    StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
                                         ArrayType::Normal, 0);
  }

  return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc);
}
Пример #4
0
QualType Sema::CheckPointerToMemberOperands(
  Expr *&lex, Expr *&rex, SourceLocation Loc, bool isIndirect)
{
  const char *OpSpelling = isIndirect ? "->*" : ".*";
  // C++ 5.5p2
  //   The binary operator .* [p3: ->*] binds its second operand, which shall
  //   be of type "pointer to member of T" (where T is a completely-defined
  //   class type) [...]
  QualType RType = rex->getType();
  const MemberPointerType *MemPtr = RType->getAsMemberPointerType();
  if (!MemPtr) {
    Diag(Loc, diag::err_bad_memptr_rhs)
      << OpSpelling << RType << rex->getSourceRange();
    return QualType();
  } else if (RequireCompleteType(Loc, QualType(MemPtr->getClass(), 0),
                                 diag::err_memptr_rhs_incomplete,
                                 rex->getSourceRange()))
    return QualType();

  QualType Class(MemPtr->getClass(), 0);

  // C++ 5.5p2
  //   [...] to its first operand, which shall be of class T or of a class of
  //   which T is an unambiguous and accessible base class. [p3: a pointer to
  //   such a class]
  QualType LType = lex->getType();
  if (isIndirect) {
    if (const PointerType *Ptr = LType->getAsPointerType())
      LType = Ptr->getPointeeType().getNonReferenceType();
    else {
      Diag(Loc, diag::err_bad_memptr_lhs)
        << OpSpelling << 1 << LType << lex->getSourceRange();
      return QualType();
    }
  }

  if (Context.getCanonicalType(Class).getUnqualifiedType() !=
      Context.getCanonicalType(LType).getUnqualifiedType()) {
    BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false,
                    /*DetectVirtual=*/false);
    // FIXME: Would it be useful to print full ambiguity paths,
    // or is that overkill?
    if (!IsDerivedFrom(LType, Class, Paths) ||
        Paths.isAmbiguous(Context.getCanonicalType(Class))) {
      Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
        << (int)isIndirect << lex->getType() << lex->getSourceRange();
      return QualType();
    }
  }

  // C++ 5.5p2
  //   The result is an object or a function of the type specified by the
  //   second operand.
  // The cv qualifiers are the union of those in the pointer and the left side,
  // in accordance with 5.5p5 and 5.2.5.
  // FIXME: This returns a dereferenced member function pointer as a normal
  // function type. However, the only operation valid on such functions is
  // calling them. There's also a GCC extension to get a function pointer to
  // the thing, which is another complication, because this type - unlike the
  // type that is the result of this expression - takes the class as the first
  // argument.
  // We probably need a "MemberFunctionClosureType" or something like that.
  QualType Result = MemPtr->getPointeeType();
  if (LType.isConstQualified())
    Result.addConst();
  if (LType.isVolatileQualified())
    Result.addVolatile();
  return Result;
}
Пример #5
0
C2::Module* C2ModuleLoader::load(const std::string& name) {

    // NOTE: MEMLEAK on Types

    clang::SourceLocation loc;

    if (name == "stdio") {
        Module* stdioMod = new C2::Module("stdio", true, true);
        // int puts(const char* s);
        {
            FunctionDecl* func = new FunctionDecl("puts", loc, true, Type::Int32());
            // TODO correct arg
            QualType QT(new PointerType(Type::Int8()), QUAL_CONST);
            QT->setCanonicalType(QT);
            VarDecl* Arg1 = new VarDecl(VARDECL_PARAM, "s", loc, QT, 0, true);
            Arg1->setType(QT);
            func->addArg(Arg1);
            stdioMod->addSymbol(func);
            // function type
            func->setType(QualType(new FunctionType(func), 0));
        }
        //int printf(const char *format, ...);
        {
            FunctionDecl* func = new FunctionDecl("printf", loc, true, Type::Int32());
            // NOTE: MEMLEAK ON TYPE, this will go away when we remove these dummy protos
            QualType QT(new PointerType(Type::Int8()), QUAL_CONST);
            QT->setCanonicalType(QT);
            VarDecl* Arg1 = new VarDecl(VARDECL_PARAM, "format", loc, QT, 0, true);
            Arg1->setType(QT);
            func->addArg(Arg1);
            func->setVariadic();
            stdioMod->addSymbol(func);
            // function type
            func->setType(QualType(new FunctionType(func), 0));
        }
        //int sprintf(char *str, const char *format, ...);
        {
            FunctionDecl* func = new FunctionDecl("sprintf", loc, true, Type::Int32());
            // NOTE: MEMLEAK ON TYPE, this will go away when we remove these dummy protos
            QualType QT(new PointerType(Type::Int8()), QUAL_CONST);
            QT->setCanonicalType(QT);
            VarDecl* Arg1 = new VarDecl(VARDECL_PARAM, "str", loc, QT, 0, true);
            Arg1->setType(QT);
            func->addArg(Arg1);
            VarDecl* Arg2 = new VarDecl(VARDECL_PARAM, "format", loc, QT, 0, true);
            Arg2->setType(QT);
            func->addArg(Arg2);
            func->setVariadic();
            stdioMod->addSymbol(func);
            // function type
            func->setType(QualType(new FunctionType(func), 0));
        }
        return stdioMod;
    }

    if (name == "string") {
        Module* stringMod = new C2::Module("string", true, true);
        // void *memset(void *s, int c, size_t n);
        {
            QualType VP(new PointerType(Type::Void()));
            VP->setCanonicalType(VP);
            FunctionDecl* func = new FunctionDecl("memset", loc, true, VP);
            // NOTE: MEMLEAK ON TYPE, this will go away when we remove these dummy protos
            VarDecl* Arg1 = new VarDecl(VARDECL_PARAM, "s", loc, VP, 0, true);
            Arg1->setType(VP);
            func->addArg(Arg1);
            VarDecl* Arg2 = new VarDecl(VARDECL_PARAM, "c", loc, Type::Int32(), 0, true);
            Arg2->setType(Type::Int32());
            func->addArg(Arg2);
            // TEMP size_t -> uint32
            VarDecl* Arg3 = new VarDecl(VARDECL_PARAM, "n", loc, Type::UInt32(), 0, true);
            Arg3->setType(Type::UInt32());
            func->addArg(Arg3);
            stringMod->addSymbol(func);
            // function type
            func->setType(QualType(new FunctionType(func), 0));
        }
        return stringMod;

    }

    if (name == "stdlib") {
        Module* stdlibMod = new C2::Module("stdlib", true, true);
        //void exit(int status);
        {
            FunctionDecl* func = new FunctionDecl("exit", loc, true, Type::Void());
            // TODO correct arg
            VarDecl* Arg1 = new VarDecl(VARDECL_PARAM, "status", loc, Type::Int32(), 0, true);
            Arg1->setType(Type::Int32());
            func->addArg(Arg1);
            stdlibMod->addSymbol(func);
            // function type
            func->setType(QualType(new FunctionType(func), 0));
        }
        return stdlibMod;
    }

    if (name == "c2") {
        Module* c2Mod = new C2::Module("c2", true, false);
        // uint64 buildtime
        {
            // make constant, CTC_NONE
            QualType QT = Type::UInt64();
            QT.addConst();
            uint64_t value = time(0);
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, value, false));
            // TODO get error without value if CTC_NONE, CTC_FULL gives out-of-bounds for value 123?!!
            init->setCTC(CTC_NONE); // Don't check range, only type
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "buildtime", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int8 min_int8
        {
            QualType QT = Type::Int8();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, -128, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_int8", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int8 max_int8
        {
            QualType QT = Type::Int8();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 127, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_int8", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint8 min_uint8
        {
            QualType QT = Type::UInt8();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 0, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_uint8", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint8 max_uint8
        {
            QualType QT = Type::UInt8();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 255, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_uint8", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int16 min_int16
        {
            QualType QT = Type::Int16();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, -32768, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_int16", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int16 max_int16
        {
            QualType QT = Type::Int16();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 32767, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_int16", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint16 min_uint16
        {
            QualType QT = Type::UInt16();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 0, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_uint16", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint16 max_uint16
        {
            QualType QT = Type::UInt16();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 65535, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_uint16", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int32 min_int32
        {
            QualType QT = Type::Int32();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, -2147483648, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_int32", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int32 max_int32
        {
            QualType QT = Type::Int32();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 2147483647, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_int32", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint32 min_uint32
        {
            QualType QT = Type::UInt32();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 0, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_uint32", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint32 max_uint32
        {
            QualType QT = Type::UInt32();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 4294967295, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_uint32", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int64 min_int64
        {
            QualType QT = Type::Int64();
            QT.addConst();
            // NOTE: minimum should be -..808, but clang complains about it..
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, -9223372036854775807ll, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_int64", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int64 max_int64
        {
            QualType QT = Type::Int64();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 9223372036854775807ll, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_int64", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint64 min_uint64
        {
            QualType QT = Type::UInt64();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 0, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_uint64", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint64 max_uint64
        {
            QualType QT = Type::UInt64();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 18446744073709551615llu, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_uint64", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        return c2Mod;
    }

    return 0;
}
Пример #6
0
void C2ModuleLoader::load(C2::Module* c2Mod) {
    clang::SourceLocation loc;

    AST* ast = new AST("<generated>", false);
    ASTContext& Context = ast->getASTContext();
    ast->setName("c2", loc);
    c2Mod->addAST(ast);

    // uint64 buildtime
    {
        // make constant, CTC_NONE
        QualType QT = Type::UInt64();
        QT.addConst();
        uint64_t value = time(0);
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, value, false));
        // TODO get error without value if CTC_NONE, CTC_FULL gives out-of-bounds for value 123?!!
        init->setCTC(CTC_NONE); // Don't check range, only type
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "buildtime", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int8 min_int8
    {
        QualType QT = Type::Int8();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, -128, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_int8", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int8 max_int8
    {
        QualType QT = Type::Int8();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 127, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_int8", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint8 min_uint8
    {
        QualType QT = Type::UInt8();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 0, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_uint8", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint8 max_uint8
    {
        QualType QT = Type::UInt8();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 255, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_uint8", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int16 min_int16
    {
        QualType QT = Type::Int16();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, -32768, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_int16", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int16 max_int16
    {
        QualType QT = Type::Int16();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 32767, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_int16", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint16 min_uint16
    {
        QualType QT = Type::UInt16();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 0, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_uint16", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint16 max_uint16
    {
        QualType QT = Type::UInt16();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 65535, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_uint16", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int32 min_int32
    {
        QualType QT = Type::Int32();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, -2147483648, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_int32", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int32 max_int32
    {
        QualType QT = Type::Int32();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 2147483647, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_int32", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint32 min_uint32
    {
        QualType QT = Type::UInt32();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 0, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_uint32", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint32 max_uint32
    {
        QualType QT = Type::UInt32();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 4294967295, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_uint32", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int64 min_int64
    {
        QualType QT = Type::Int64();
        QT.addConst();
        // NOTE: minimum should be -..808, but clang complains about it..
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, -9223372036854775807ll, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_int64", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int64 max_int64
    {
        QualType QT = Type::Int64();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 9223372036854775807ll, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_int64", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint64 min_uint64
    {
        QualType QT = Type::UInt64();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 0, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_uint64", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint64 max_uint64
    {
        QualType QT = Type::UInt64();
        QT.addConst();
        // NOTE: capped to -1 since APInt is always signed?
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 18446744073709551615llu, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_uint64", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }

#if 0
    // type c_char int8
    {
        QualType QT = Type::Int8();
        static const char* name = "c_char";
        AliasTypeDecl* T = new (Context) AliasTypeDecl(name, loc, QT, true);
        QualType A = Context.getAliasType(T, QT);
        A->setCanonicalType(QT);
        T->setType(A);
        c2Mod->addSymbol(T);
    }
#endif
    // create C types (depend on target)
    // NOTE: all types are lower-cased!
    for (unsigned i=0; i<sizeof(ctypes)/sizeof(ctypes[0]); i++) {
        QualType QT = ctypes[i].type;
        AliasTypeDecl* T = new (Context) AliasTypeDecl(ctypes[i].name, loc, QT, true);
        QualType A = Context.getAliasType(T, QT);
        A->setCanonicalType(QT);
        T->setType(A);
        ast->addType(T);
        c2Mod->addSymbol(T);
    }
}