зеркало из https://github.com/microsoft/clang-1.git
move GetBuiltinType from Builtin::Context to ASTContext.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73316 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
7b3684afff
Коммит
86df27bbdb
|
@ -455,6 +455,14 @@ public:
|
|||
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name);
|
||||
|
||||
enum GetBuiltinTypeError {
|
||||
GE_None, //< No error
|
||||
GE_Missing_FILE //< Missing the FILE type from <stdio.h>
|
||||
};
|
||||
|
||||
/// GetBuiltinType - Return the type for the specified builtin.
|
||||
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error);
|
||||
|
||||
private:
|
||||
QualType getFromTargetType(unsigned Type) const;
|
||||
|
||||
|
|
|
@ -72,6 +72,11 @@ public:
|
|||
return GetRecord(ID).Name;
|
||||
}
|
||||
|
||||
/// GetTypeString - Get the type descriptor string for the specified builtin.
|
||||
const char *GetTypeString(unsigned ID) const {
|
||||
return GetRecord(ID).Type;
|
||||
}
|
||||
|
||||
/// isConst - Return true if this function has no side effects and doesn't
|
||||
/// read memory.
|
||||
bool isConst(unsigned ID) const {
|
||||
|
@ -121,13 +126,6 @@ public:
|
|||
return strchr(GetRecord(ID).Attributes, 'e') != 0;
|
||||
}
|
||||
|
||||
/// GetBuiltinType - Return the type for the specified builtin.
|
||||
enum GetBuiltinTypeError {
|
||||
GE_None, //< No error
|
||||
GE_Missing_FILE //< Missing the FILE type from <stdio.h>
|
||||
};
|
||||
QualType GetBuiltinType(unsigned ID, ASTContext &Context,
|
||||
GetBuiltinTypeError &Error) const;
|
||||
private:
|
||||
const Info &GetRecord(unsigned ID) const;
|
||||
};
|
||||
|
|
|
@ -3375,3 +3375,203 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
|
|||
ExternalASTSource::~ExternalASTSource() { }
|
||||
|
||||
void ExternalASTSource::PrintStats() { }
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Builtin Type Computation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// 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,
|
||||
ASTContext::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 = ASTContext::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;
|
||||
}
|
||||
|
||||
/// GetBuiltinType - Return the type for the specified builtin.
|
||||
QualType ASTContext::GetBuiltinType(unsigned id,
|
||||
GetBuiltinTypeError &Error) {
|
||||
const char *TypeStr = BuiltinInfo.GetTypeString(id);
|
||||
|
||||
llvm::SmallVector<QualType, 8> ArgTypes;
|
||||
|
||||
Error = GE_None;
|
||||
QualType ResType = DecodeTypeFromStr(TypeStr, *this, Error);
|
||||
if (Error != GE_None)
|
||||
return QualType();
|
||||
while (TypeStr[0] && TypeStr[0] != '.') {
|
||||
QualType Ty = DecodeTypeFromStr(TypeStr, *this, Error);
|
||||
if (Error != GE_None)
|
||||
return QualType();
|
||||
|
||||
// Do array -> pointer decay. The builtin should use the decayed type.
|
||||
if (Ty->isArrayType())
|
||||
Ty = getArrayDecayedType(Ty);
|
||||
|
||||
ArgTypes.push_back(Ty);
|
||||
}
|
||||
|
||||
assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
|
||||
"'.' should only occur at end of builtin type list!");
|
||||
|
||||
// handle untyped/variadic arguments "T c99Style();" or "T cppStyle(...);".
|
||||
if (ArgTypes.size() == 0 && TypeStr[0] == '.')
|
||||
return getFunctionNoProtoType(ResType);
|
||||
return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(),
|
||||
TypeStr[0] == '.', 0);
|
||||
}
|
||||
|
|
|
@ -94,197 +94,3 @@ Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
|
|||
return true;
|
||||
}
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// GetBuiltinType - Return the type for the specified builtin.
|
||||
QualType Builtin::Context::GetBuiltinType(unsigned id, ASTContext &Context,
|
||||
GetBuiltinTypeError &Error) const {
|
||||
const char *TypeStr = GetRecord(id).Type;
|
||||
|
||||
llvm::SmallVector<QualType, 8> ArgTypes;
|
||||
|
||||
Error = GE_None;
|
||||
QualType ResType = DecodeTypeFromStr(TypeStr, Context, Error);
|
||||
if (Error != GE_None)
|
||||
return QualType();
|
||||
while (TypeStr[0] && TypeStr[0] != '.') {
|
||||
QualType Ty = DecodeTypeFromStr(TypeStr, Context, Error);
|
||||
if (Error != GE_None)
|
||||
return QualType();
|
||||
|
||||
// Do array -> pointer decay. The builtin should use the decayed type.
|
||||
if (Ty->isArrayType())
|
||||
Ty = Context.getArrayDecayedType(Ty);
|
||||
|
||||
ArgTypes.push_back(Ty);
|
||||
}
|
||||
|
||||
assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
|
||||
"'.' should only occur at end of builtin type list!");
|
||||
|
||||
// handle untyped/variadic arguments "T c99Style();" or "T cppStyle(...);".
|
||||
if (ArgTypes.size() == 0 && TypeStr[0] == '.')
|
||||
return Context.getFunctionNoProtoType(ResType);
|
||||
return Context.getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(),
|
||||
TypeStr[0] == '.', 0);
|
||||
}
|
||||
|
|
|
@ -1107,9 +1107,9 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(unsigned BuiltinID) {
|
|||
Name += 10;
|
||||
|
||||
// Get the type for the builtin.
|
||||
Builtin::Context::GetBuiltinTypeError Error;
|
||||
QualType Type = Context.BuiltinInfo.GetBuiltinType(BuiltinID, Context, Error);
|
||||
assert(Error == Builtin::Context::GE_None && "Can't get builtin type");
|
||||
ASTContext::GetBuiltinTypeError Error;
|
||||
QualType Type = Context.GetBuiltinType(BuiltinID, Error);
|
||||
assert(Error == ASTContext::GE_None && "Can't get builtin type");
|
||||
|
||||
const llvm::FunctionType *Ty =
|
||||
cast<llvm::FunctionType>(getTypes().ConvertType(Type));
|
||||
|
|
|
@ -416,14 +416,14 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
|
|||
if (Context.BuiltinInfo.hasVAListUse(BID))
|
||||
InitBuiltinVaListType();
|
||||
|
||||
Builtin::Context::GetBuiltinTypeError Error;
|
||||
QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context, Error);
|
||||
ASTContext::GetBuiltinTypeError Error;
|
||||
QualType R = Context.GetBuiltinType(BID, Error);
|
||||
switch (Error) {
|
||||
case Builtin::Context::GE_None:
|
||||
case ASTContext::GE_None:
|
||||
// Okay
|
||||
break;
|
||||
|
||||
case Builtin::Context::GE_Missing_FILE:
|
||||
case ASTContext::GE_Missing_FILE:
|
||||
if (ForRedeclaration)
|
||||
Diag(Loc, diag::err_implicit_decl_requires_stdio)
|
||||
<< Context.BuiltinInfo.GetName(BID);
|
||||
|
|
Загрузка…
Ссылка в новой задаче