From: Chris Lattner Date: Sun, 14 Jun 2009 00:45:47 +0000 (+0000) Subject: move GetBuiltinType from Builtin::Context to ASTContext. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=86df27bbdbb98c39ec2184695c0561209f91bedd;p=clang move GetBuiltinType from Builtin::Context to ASTContext. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73316 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index b02faa8ff3..cd8178de1f 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -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 + }; + + /// GetBuiltinType - Return the type for the specified builtin. + QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error); + private: QualType getFromTargetType(unsigned Type) const; diff --git a/include/clang/AST/Builtins.h b/include/clang/AST/Builtins.h index b16d3bf341..007e8dea8d 100644 --- a/include/clang/AST/Builtins.h +++ b/include/clang/AST/Builtins.h @@ -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 - }; - QualType GetBuiltinType(unsigned ID, ASTContext &Context, - GetBuiltinTypeError &Error) const; private: const Info &GetRecord(unsigned ID) const; }; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index fb28fd4367..4891fd3f73 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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(*Lookup.first)) { + Type = Context.getTypeDeclType(cast(*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 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); +} diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index 8368febe5a..36476ae355 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -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(*Lookup.first)) { - Type = Context.getTypeDeclType(cast(*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 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); -} diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 8ca1be42e7..16d0ec9582 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -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(getTypes().ConvertType(Type)); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 3a4aeb79a1..b995717ac8 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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);