diff options
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 217 |
1 files changed, 205 insertions, 12 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index fb28fd4..7ed9e45 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -18,6 +18,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/RecordLayout.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringExtras.h" @@ -32,18 +33,15 @@ enum FloatingRank { ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, - bool FreeMem, unsigned size_reserve, - bool InitializeBuiltins) : + Builtin::Context &builtins, + bool FreeMem, unsigned size_reserve) : GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0), SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels), - ExternalSource(0) { + BuiltinInfo(builtins), ExternalSource(0) { if (size_reserve > 0) Types.reserve(size_reserve); InitBuiltinTypes(); TUDecl = TranslationUnitDecl::Create(*this); - BuiltinInfo.InitializeTargetBuiltins(Target); - if (InitializeBuiltins) - this->InitializeBuiltins(idents); PrintingPolicy.CPlusPlus = LangOpts.CPlusPlus; } @@ -86,10 +84,6 @@ ASTContext::~ASTContext() { TUDecl->Destroy(*this); } -void ASTContext::InitializeBuiltins(IdentifierTable &idents) { - BuiltinInfo.InitializeBuiltins(idents, LangOpts.NoBuiltin); -} - void ASTContext::setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source) { ExternalSource.reset(Source.take()); @@ -1979,9 +1973,8 @@ unsigned ASTContext::getIntegerRank(Type *T) { // There are two things which impact the integer rank: the width, and // the ordering of builtins. The builtin ordering is encoded in the // bottom three bits; the width is encoded in the bits above that. - if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T)) { + if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T)) return FWIT->getWidth() << 3; - } switch (cast<BuiltinType>(T)->getKind()) { default: assert(0 && "getIntegerRank(): not a built-in integer"); @@ -3375,3 +3368,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); +} |