/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the /// pointer over the consumed characters. This returns the resultant type. static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, Builtin::Context::GetBuiltinTypeError &Error, bool AllowTypeModifiers = true) { // Modifiers. int HowLong = 0; bool Signed = false, Unsigned = false; // Read the modifiers first. bool Done = false; while (!Done) { switch (*Str++) { default: Done = true; --Str; break; case 'S': assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!"); assert(!Signed && "Can't use 'S' modifier multiple times!"); Signed = true; break; case 'U': assert(!Signed && "Can't use both 'S' and 'U' modifiers!"); assert(!Unsigned && "Can't use 'S' modifier multiple times!"); Unsigned = true; break; case 'L': assert(HowLong <= 2 && "Can't have LLLL modifier"); ++HowLong; break; } } QualType Type; // Read the base type. switch (*Str++) { default: assert(0 && "Unknown builtin type letter!"); case 'v': assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers used with 'v'!"); Type = Context.VoidTy; break; case 'f': assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers used with 'f'!"); Type = Context.FloatTy; break; case 'd': assert(HowLong < 2 && !Signed && !Unsigned && "Bad modifiers used with 'd'!"); if (HowLong) Type = Context.LongDoubleTy; else Type = Context.DoubleTy; break; case 's': assert(HowLong == 0 && "Bad modifiers used with 's'!"); if (Unsigned) Type = Context.UnsignedShortTy; else Type = Context.ShortTy; break; case 'i': if (HowLong == 3) Type = Unsigned ? Context.UnsignedInt128Ty : Context.Int128Ty; else if (HowLong == 2) Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy; else if (HowLong == 1) Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy; else Type = Unsigned ? Context.UnsignedIntTy : Context.IntTy; break; case 'c': assert(HowLong == 0 && "Bad modifiers used with 'c'!"); if (Signed) Type = Context.SignedCharTy; else if (Unsigned) Type = Context.UnsignedCharTy; else Type = Context.CharTy; break; case 'b': // boolean assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!"); Type = Context.BoolTy; break; case 'z': // size_t. assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!"); Type = Context.getSizeType(); break; case 'F': Type = Context.getCFConstantStringType(); break; case 'a': Type = Context.getBuiltinVaListType(); assert(!Type.isNull() && "builtin va list type not initialized!"); break; case 'A': // This is a "reference" to a va_list; however, what exactly // this means depends on how va_list is defined. There are two // different kinds of va_list: ones passed by value, and ones // passed by reference. An example of a by-value va_list is // x86, where va_list is a char*. An example of by-ref va_list // is x86-64, where va_list is a __va_list_tag[1]. For x86, // we want this argument to be a char*&; for x86-64, we want // it to be a __va_list_tag*. Type = Context.getBuiltinVaListType(); assert(!Type.isNull() && "builtin va list type not initialized!"); if (Type->isArrayType()) { Type = Context.getArrayDecayedType(Type); } else { Type = Context.getLValueReferenceType(Type); } break; case 'V': { char *End; unsigned NumElements = strtoul(Str, &End, 10); assert(End != Str && "Missing vector size"); Str = End; QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false); Type = Context.getVectorType(ElementType, NumElements); break; } case 'P': { IdentifierInfo *II = &Context.Idents.get("FILE"); DeclContext::lookup_result Lookup = Context.getTranslationUnitDecl()->lookup(Context, II); if (Lookup.first != Lookup.second && isa<TypeDecl>(*Lookup.first)) { Type = Context.getTypeDeclType(cast<TypeDecl>(*Lookup.first)); break; } else { Error = Builtin::Context::GE_Missing_FILE; return QualType(); } } } if (!AllowTypeModifiers) return Type; Done = false; while (!Done) { switch (*Str++) { default: Done = true; --Str; break; case '*': Type = Context.getPointerType(Type); break; case '&': Type = Context.getLValueReferenceType(Type); break; // FIXME: There's no way to have a built-in with an rvalue ref arg. case 'C': Type = Type.getQualifiedType(QualType::Const); break; } } return Type; }
//===----------------------------------------------------------------------===// // Builtin Type Computation //===----------------------------------------------------------------------===// /// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the /// pointer over the consumed characters. This returns the resultant type. If /// AllowTypeModifiers is false then modifier like * are not parsed, just basic /// types. This allows "v2i*" to be parsed as a pointer to a v2i instead of /// a vector of "i*". /// /// RequiresICE is filled in on return to indicate whether the value is required /// to be an Integer Constant Expression. static Type DecodeTypeFromStr(const char *&Str, const ASTContext &Context, ASTContext::GetBuiltinTypeError &Error, bool &RequiresICE, bool AllowTypeModifiers) { // Modifiers. int HowLong = 0; bool Signed = false, Unsigned = false; RequiresICE = false; // Read the prefixed modifiers first. bool Done = false; while (!Done) { switch (*Str++) { default: Done = true; --Str; break; case 'I': RequiresICE = true; break; case 'S': assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!"); assert(!Signed && "Can't use 'S' modifier multiple times!"); Signed = true; break; case 'U': assert(!Signed && "Can't use both 'S' and 'U' modifiers!"); assert(!Unsigned && "Can't use 'S' modifier multiple times!"); Unsigned = true; break; case 'L': assert(HowLong < 4 && "Can't have LLLL modifier"); ++HowLong; break; } } Type Ty; // Read the base type. switch (*Str++) { default: assert(0 && "Unknown builtin type letter!"); case 'v': assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers used with 'v'!"); // Ty = Context.VoidTy; break; case 'f': assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers used with 'f'!"); Ty = Context.SingleTy; break; case 'd': assert(HowLong < 2 && !Signed && !Unsigned && "Bad modifiers used with 'd'!"); Ty = Context.DoubleTy; break; case 's': assert(HowLong == 0 && "Bad modifiers used with 's'!"); // if (Unsigned) // Ty = Context.UnsignedShortTy; // else // Ty = Context.ShortTy; break; case 'i': if (HowLong == 3) Ty = Unsigned ? Context.UInt64Ty : Context.Int64Ty; else if (HowLong == 2) Ty = Unsigned ? Context.UInt32Ty : Context.Int32Ty; else if (HowLong == 1) Ty = Unsigned ? Context.UInt16Ty : Context.Int16Ty; else Ty = Unsigned ? Context.UInt8Ty : Context.Int8Ty; break; case 'c': assert(HowLong == 0 && "Bad modifiers used with 'c'!"); Ty = Context.CharTy; break; case 'b': // boolean assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!"); Ty = Context.LogicalTy; break; case 'z': // size_t. assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!"); // Ty = Context.getSizeType(); break; case 'F': //Ty = Context.getCFConstantStringType(); break; case 'G': //Ty = Context.getObjCIdType(); break; case 'H': //Ty = Context.getObjCSelType(); break; case 'a': //Ty = Context.getBuiltinVaListType(); //assert(!Ty.isNull() && "builtin va list type not initialized!"); break; case 'A': // This is a "reference" to a va_list; however, what exactly // this means depends on how va_list is defined. There are two // different kinds of va_list: ones passed by value, and ones // passed by reference. An example of a by-value va_list is // x86, where va_list is a char*. An example of by-ref va_list // is x86-64, where va_list is a __va_list_tag[1]. For x86, // we want this argument to be a char*&; for x86-64, we want // it to be a __va_list_tag*. // Ty = Context.getBuiltinVaListType(); // assert(!Ty.isNull() && "builtin va list type not initialized!"); // if (Ty->isArrayType()) // Ty = Context.getArrayDecayedType(Ty); // else // Ty = Context.getLValueReferenceType(Ty); break; case 'V': { char *End; unsigned NumElements = strtoul(Str, &End, 10); assert(End != Str && "Missing vector size"); Str = End; Type ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE, false); assert(!RequiresICE && "Can't require vector ICE"); // TODO: No way to make AltiVec vectors in builtins yet. Ty = Context.getVectorType(ElementType, NumElements, VectorType::GenericVector, true); break; } case 'X': { Type ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE, false); assert(!RequiresICE && "Can't require complex ICE"); // Ty = Context.getComplexType(ElementType); break; } case 'P': // Ty = Context.getFILEType(); // if (Ty.isNull()) { // Error = ASTContext::GE_Missing_stdio; return Type(); // } // break; case 'J': // if (Signed) // Ty = Context.getsigjmp_bufType(); // else // Ty = Context.getjmp_bufType(); if (Ty.isNull()) { Error = ASTContext::GE_Missing_setjmp; return Type(); } break; } // If there are modifiers and if we're allowed to parse them, go for it. Done = !AllowTypeModifiers; while (!Done) { switch (/*char c =*/ *Str++) { default: Done = true; --Str; break; case '*': case '&': { // Both pointers and references can have their pointee types // qualified with an address space. char *End; unsigned AddrSpace = strtoul(Str, &End, 10); if (End != Str && AddrSpace != 0) { // Ty = Context.getAddrSpaceQualType(Ty, AddrSpace); Str = End; } // if (c == '*') // Ty = Context.getPointerType(Ty); // else // Ty = Context.getLValueReferenceType(Ty); // break; } // FIXME: There's no way to have a built-in with an rvalue ref arg. case 'C': // Ty = Ty.withConst(); break; case 'D': // Ty = Context.getVolatileType(Ty); break; } } assert((!RequiresICE || Ty->isIntegerType()) && "Integer constant 'I' type must be an integer"); return Ty; }