diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/ASTContext.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/ASTContext.cpp | 816 |
1 files changed, 533 insertions, 283 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 176aec5..a03cf9e7 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -25,13 +25,16 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Mangle.h" +#include "clang/AST/MangleNumberingContext.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/Capacity.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -132,8 +135,14 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { isa<RedeclarableTemplateDecl>(D) || isa<ClassTemplateSpecializationDecl>(D)) DeclLoc = D->getLocStart(); - else + else { DeclLoc = D->getLocation(); + // If location of the typedef name is in a macro, it is because being + // declared via a macro. Try using declaration's starting location + // as the "declaration location". + if (DeclLoc.isMacroID() && isa<TypedefDecl>(D)) + DeclLoc = D->getLocStart(); + } // If the declaration doesn't map directly to a location in a file, we // can't find the comment. @@ -175,7 +184,8 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // First check whether we have a trailing comment. if (Comment != RawComments.end() && (*Comment)->isDocumentation() && (*Comment)->isTrailingComment() && - (isa<FieldDecl>(D) || isa<EnumConstantDecl>(D) || isa<VarDecl>(D))) { + (isa<FieldDecl>(D) || isa<EnumConstantDecl>(D) || isa<VarDecl>(D) || + isa<ObjCMethodDecl>(D) || isa<ObjCPropertyDecl>(D))) { std::pair<FileID, unsigned> CommentBeginDecomp = SourceMgr.getDecomposedLoc((*Comment)->getSourceRange().getBegin()); // Check that Doxygen trailing comment comes after the declaration, starts @@ -220,7 +230,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // There should be no other declarations or preprocessor directives between // comment and declaration. - if (Text.find_first_of(",;{}#@") != StringRef::npos) + if (Text.find_first_of(";{}#@") != StringRef::npos) return NULL; return *Comment; @@ -406,9 +416,16 @@ comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC, } +comments::FullComment *ASTContext::getLocalCommentForDeclUncached(const Decl *D) const { + const RawComment *RC = getRawCommentForDeclNoCache(D); + return RC ? RC->parse(*this, 0, D) : 0; +} + comments::FullComment *ASTContext::getCommentForDecl( const Decl *D, const Preprocessor *PP) const { + if (D->isInvalidDecl()) + return NULL; D = adjustDeclToTemplate(D); const Decl *Canonical = D->getCanonicalDecl(); @@ -679,6 +696,19 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, } } +static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI, + const LangOptions &LangOpts) { + switch (LangOpts.getAddressSpaceMapMangling()) { + case LangOptions::ASMM_Target: + return TI.useAddressSpaceMapMangling(); + case LangOptions::ASMM_On: + return true; + case LangOptions::ASMM_Off: + return false; + } + llvm_unreachable("getAddressSpaceMapMangling() doesn't cover anything."); +} + ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, const TargetInfo *t, IdentifierTable &idents, SelectorTable &sels, @@ -690,7 +720,7 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, DependentTemplateSpecializationTypes(this_()), SubstTemplateTemplateParmPacks(this_()), GlobalNestedNameSpecifier(0), - Int128Decl(0), UInt128Decl(0), + Int128Decl(0), UInt128Decl(0), Float128StubDecl(0), BuiltinVaListDecl(0), ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), ObjCProtocolClassDecl(0), BOOLDecl(0), @@ -709,8 +739,7 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, ExternalSource(0), Listener(0), Comments(SM), CommentsLoaded(false), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), - LastSDM(0, 0), - UniqueBlockByRefTypeID(0) + LastSDM(0, 0) { if (size_reserve > 0) Types.reserve(size_reserve); TUDecl = TranslationUnitDecl::Create(*this); @@ -726,10 +755,12 @@ ASTContext::~ASTContext() { // FIXME: Is this the ideal solution? ReleaseDeclContextMaps(); - // Call all of the deallocation functions. - for (unsigned I = 0, N = Deallocations.size(); I != N; ++I) - Deallocations[I].first(Deallocations[I].second); - + // Call all of the deallocation functions on all of their targets. + for (DeallocationMap::const_iterator I = Deallocations.begin(), + E = Deallocations.end(); I != E; ++I) + for (unsigned J = 0, N = I->second.size(); J != N; ++J) + (I->first)((I->second)[J]); + // ASTRecordLayout objects in ASTRecordLayouts must always be destroyed // because they can contain DenseMaps. for (llvm::DenseMap<const ObjCContainerDecl*, @@ -750,10 +781,16 @@ ASTContext::~ASTContext() { AEnd = DeclAttrs.end(); A != AEnd; ++A) A->second->~AttrVec(); + + for (llvm::DenseMap<const DeclContext *, MangleNumberingContext *>::iterator + I = MangleNumberingContexts.begin(), + E = MangleNumberingContexts.end(); + I != E; ++I) + delete I->second; } void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { - Deallocations.push_back(std::make_pair(Callback, Data)); + Deallocations[Callback].push_back(Data); } void @@ -848,6 +885,20 @@ TypedefDecl *ASTContext::getUInt128Decl() const { return UInt128Decl; } +TypeDecl *ASTContext::getFloat128StubType() const { + assert(LangOpts.CPlusPlus && "should only be called for c++"); + if (!Float128StubDecl) { + Float128StubDecl = CXXRecordDecl::Create(const_cast<ASTContext &>(*this), + TTK_Struct, + getTranslationUnitDecl(), + SourceLocation(), + SourceLocation(), + &Idents.get("__float128")); + } + + return Float128StubDecl; +} + void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K); R = CanQualType::CreateUnsafe(QualType(Ty, 0)); @@ -863,6 +914,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { ABI.reset(createCXXABI(Target)); AddrSpaceMap = getAddressSpaceMap(Target, LangOpts); + AddrSpaceMapMangling = isAddrSpaceMapManglingEnabled(Target, LangOpts); // C99 6.2.5p19. InitBuiltinType(VoidTy, BuiltinType::Void); @@ -897,13 +949,17 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); - if (LangOpts.CPlusPlus && LangOpts.WChar) { // C++ 3.9.1p5 - if (TargetInfo::isTypeSigned(Target.getWCharType())) - InitBuiltinType(WCharTy, BuiltinType::WChar_S); - else // -fshort-wchar makes wchar_t be unsigned. - InitBuiltinType(WCharTy, BuiltinType::WChar_U); - } else // C99 (or C++ using -fno-wchar) - WCharTy = getFromTargetType(Target.getWCharType()); + // C++ 3.9.1p5 + if (TargetInfo::isTypeSigned(Target.getWCharType())) + InitBuiltinType(WCharTy, BuiltinType::WChar_S); + else // -fshort-wchar makes wchar_t be unsigned. + InitBuiltinType(WCharTy, BuiltinType::WChar_U); + if (LangOpts.CPlusPlus && LangOpts.WChar) + WideCharTy = WCharTy; + else { + // C99 (or C++ using -fno-wchar). + WideCharTy = getFromTargetType(Target.getWCharType()); + } WIntTy = getFromTargetType(Target.getWIntType()); @@ -1008,13 +1064,20 @@ void ASTContext::eraseDeclAttrs(const Decl *D) { } } +// FIXME: Remove ? MemberSpecializationInfo * ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) { assert(Var->isStaticDataMember() && "Not a static data member"); - llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>::iterator Pos - = InstantiatedFromStaticDataMember.find(Var); - if (Pos == InstantiatedFromStaticDataMember.end()) - return 0; + return getTemplateOrSpecializationInfo(Var) + .dyn_cast<MemberSpecializationInfo *>(); +} + +ASTContext::TemplateOrSpecializationInfo +ASTContext::getTemplateOrSpecializationInfo(const VarDecl *Var) { + llvm::DenseMap<const VarDecl *, TemplateOrSpecializationInfo>::iterator Pos = + TemplateOrInstantiation.find(Var); + if (Pos == TemplateOrInstantiation.end()) + return TemplateOrSpecializationInfo(); return Pos->second; } @@ -1025,10 +1088,16 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, SourceLocation PointOfInstantiation) { assert(Inst->isStaticDataMember() && "Not a static data member"); assert(Tmpl->isStaticDataMember() && "Not a static data member"); - assert(!InstantiatedFromStaticDataMember[Inst] && - "Already noted what static data member was instantiated from"); - InstantiatedFromStaticDataMember[Inst] - = new (*this) MemberSpecializationInfo(Tmpl, TSK, PointOfInstantiation); + setTemplateOrSpecializationInfo(Inst, new (*this) MemberSpecializationInfo( + Tmpl, TSK, PointOfInstantiation)); +} + +void +ASTContext::setTemplateOrSpecializationInfo(VarDecl *Inst, + TemplateOrSpecializationInfo TSI) { + assert(!TemplateOrInstantiation[Inst] && + "Already noted what the variable was instantiated from"); + TemplateOrInstantiation[Inst] = TSI; } FunctionDecl *ASTContext::getClassScopeSpecializationPattern( @@ -1105,38 +1174,6 @@ void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, InstantiatedFromUnnamedFieldDecl[Inst] = Tmpl; } -bool ASTContext::ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const { - return (FD->isBitField() && LastFD && !LastFD->isBitField() && - FD->getBitWidthValue(*this) == 0); -} - -bool ASTContext::ZeroBitfieldFollowsBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const { - return (FD->isBitField() && LastFD && LastFD->isBitField() && - FD->getBitWidthValue(*this) == 0 && - LastFD->getBitWidthValue(*this) != 0); -} - -bool ASTContext::BitfieldFollowsBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const { - return (FD->isBitField() && LastFD && LastFD->isBitField() && - FD->getBitWidthValue(*this) && - LastFD->getBitWidthValue(*this)); -} - -bool ASTContext::NonBitfieldFollowsBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const { - return (!FD->isBitField() && LastFD && LastFD->isBitField() && - LastFD->getBitWidthValue(*this)); -} - -bool ASTContext::BitfieldFollowsNonBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const { - return (FD->isBitField() && LastFD && !LastFD->isBitField() && - FD->getBitWidthValue(*this)); -} - ASTContext::overridden_cxx_method_iterator ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const { llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos @@ -1224,12 +1261,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { } } -/// getDeclAlign - Return a conservative estimate of the alignment of the -/// specified decl. Note that bitfields do not have a valid alignment, so -/// this method will assert on them. -/// If @p RefAsPointee, references are treated like their underlying type -/// (for alignof), else they're treated like pointers (for CodeGen). -CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { +CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { unsigned Align = Target->getCharWidth(); bool UseAlignAttrOnly = false; @@ -1262,7 +1294,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { } else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { QualType T = VD->getType(); if (const ReferenceType* RT = T->getAs<ReferenceType>()) { - if (RefAsPointee) + if (ForAlignof) T = RT->getPointeeType(); else T = getPointerType(RT->getPointeeType()); @@ -1270,14 +1302,15 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { if (!T->isIncompleteType() && !T->isFunctionType()) { // Adjust alignments of declarations with array type by the // large-array alignment on the target. - unsigned MinWidth = Target->getLargeArrayMinWidth(); - const ArrayType *arrayType; - if (MinWidth && (arrayType = getAsArrayType(T))) { - if (isa<VariableArrayType>(arrayType)) - Align = std::max(Align, Target->getLargeArrayAlign()); - else if (isa<ConstantArrayType>(arrayType) && - MinWidth <= getTypeSize(cast<ConstantArrayType>(arrayType))) - Align = std::max(Align, Target->getLargeArrayAlign()); + if (const ArrayType *arrayType = getAsArrayType(T)) { + unsigned MinWidth = Target->getLargeArrayMinWidth(); + if (!ForAlignof && MinWidth) { + if (isa<VariableArrayType>(arrayType)) + Align = std::max(Align, Target->getLargeArrayAlign()); + else if (isa<ConstantArrayType>(arrayType) && + MinWidth <= getTypeSize(cast<ConstantArrayType>(arrayType))) + Align = std::max(Align, Target->getLargeArrayAlign()); + } // Walk through any array types while we're at it. T = getBaseElementType(arrayType); @@ -1294,24 +1327,27 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { // a max-field-alignment constraint (#pragma pack). So calculate // the actual alignment of the field within the struct, and then // (as we're expected to) constrain that by the alignment of the type. - if (const FieldDecl *field = dyn_cast<FieldDecl>(VD)) { - // So calculate the alignment of the field. - const ASTRecordLayout &layout = getASTRecordLayout(field->getParent()); - - // Start with the record's overall alignment. - unsigned fieldAlign = toBits(layout.getAlignment()); - - // Use the GCD of that and the offset within the record. - uint64_t offset = layout.getFieldOffset(field->getFieldIndex()); - if (offset > 0) { - // Alignment is always a power of 2, so the GCD will be a power of 2, - // which means we get to do this crazy thing instead of Euclid's. - uint64_t lowBitOfOffset = offset & (~offset + 1); - if (lowBitOfOffset < fieldAlign) - fieldAlign = static_cast<unsigned>(lowBitOfOffset); - } + if (const FieldDecl *Field = dyn_cast<FieldDecl>(VD)) { + const RecordDecl *Parent = Field->getParent(); + // We can only produce a sensible answer if the record is valid. + if (!Parent->isInvalidDecl()) { + const ASTRecordLayout &Layout = getASTRecordLayout(Parent); + + // Start with the record's overall alignment. + unsigned FieldAlign = toBits(Layout.getAlignment()); + + // Use the GCD of that and the offset within the record. + uint64_t Offset = Layout.getFieldOffset(Field->getFieldIndex()); + if (Offset > 0) { + // Alignment is always a power of 2, so the GCD will be a power of 2, + // which means we get to do this crazy thing instead of Euclid's. + uint64_t LowBitOfOffset = Offset & (~Offset + 1); + if (LowBitOfOffset < FieldAlign) + FieldAlign = static_cast<unsigned>(LowBitOfOffset); + } - Align = std::min(Align, fieldAlign); + Align = std::min(Align, FieldAlign); + } } } @@ -1339,8 +1375,30 @@ ASTContext::getTypeInfoDataSizeInChars(QualType T) const { return sizeAndAlign; } +/// getConstantArrayInfoInChars - Performing the computation in CharUnits +/// instead of in bits prevents overflowing the uint64_t for some large arrays. +std::pair<CharUnits, CharUnits> +static getConstantArrayInfoInChars(const ASTContext &Context, + const ConstantArrayType *CAT) { + std::pair<CharUnits, CharUnits> EltInfo = + Context.getTypeInfoInChars(CAT->getElementType()); + uint64_t Size = CAT->getSize().getZExtValue(); + assert((Size == 0 || static_cast<uint64_t>(EltInfo.first.getQuantity()) <= + (uint64_t)(-1)/Size) && + "Overflow in array type char size evaluation"); + uint64_t Width = EltInfo.first.getQuantity() * Size; + unsigned Align = EltInfo.second.getQuantity(); + if (!Context.getTargetInfo().getCXXABI().isMicrosoft() || + Context.getTargetInfo().getPointerWidth(0) == 64) + Width = llvm::RoundUpToAlignment(Width, Align); + return std::make_pair(CharUnits::fromQuantity(Width), + CharUnits::fromQuantity(Align)); +} + std::pair<CharUnits, CharUnits> ASTContext::getTypeInfoInChars(const Type *T) const { + if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) + return getConstantArrayInfoInChars(*this, CAT); std::pair<uint64_t, unsigned> Info = getTypeInfo(T); return std::make_pair(toCharUnitsFromBits(Info.first), toCharUnitsFromBits(Info.second)); @@ -1376,6 +1434,10 @@ ASTContext::getTypeInfoImpl(const Type *T) const { #define ABSTRACT_TYPE(Class, Base) #define NON_CANONICAL_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) \ + case Type::Class: \ + assert(!T->isDependentType() && "should not see dependent types here"); \ + return getTypeInfo(cast<Class##Type>(T)->desugar().getTypePtr()); #include "clang/AST/TypeNodes.def" llvm_unreachable("Should not see dependent types"); @@ -1401,7 +1463,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const { "Overflow in array type bit size evaluation"); Width = EltInfo.first*Size; Align = EltInfo.second; - Width = llvm::RoundUpToAlignment(Width, Align); + if (!getTargetInfo().getCXXABI().isMicrosoft() || + getTargetInfo().getPointerWidth(0) == 64) + Width = llvm::RoundUpToAlignment(Width, Align); break; } case Type::ExtVector: @@ -1568,6 +1632,8 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::ObjCObject: return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr()); + case Type::Decayed: + return getTypeInfo(cast<DecayedType>(T)->getDecayedType().getTypePtr()); case Type::ObjCInterface: { const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T); const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); @@ -1624,20 +1690,6 @@ ASTContext::getTypeInfoImpl(const Type *T) const { break; } - case Type::TypeOfExpr: - return getTypeInfo(cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType() - .getTypePtr()); - - case Type::TypeOf: - return getTypeInfo(cast<TypeOfType>(T)->getUnderlyingType().getTypePtr()); - - case Type::Decltype: - return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType() - .getTypePtr()); - - case Type::UnaryTransform: - return getTypeInfo(cast<UnaryTransformType>(T)->getUnderlyingType()); - case Type::Elaborated: return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr()); @@ -1645,18 +1697,6 @@ ASTContext::getTypeInfoImpl(const Type *T) const { return getTypeInfo( cast<AttributedType>(T)->getEquivalentType().getTypePtr()); - case Type::TemplateSpecialization: { - assert(getCanonicalType(T) != T && - "Cannot request the size of a dependent type"); - const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T); - // A type alias template specialization may refer to a typedef with the - // aligned attribute on it. - if (TST->isTypeAlias()) - return getTypeInfo(TST->getAliasedType().getTypePtr()); - else - return getTypeInfo(getCanonicalType(T)); - } - case Type::Atomic: { // Start with the base type information. std::pair<uint64_t, unsigned> Info @@ -1696,10 +1736,10 @@ int64_t ASTContext::toBits(CharUnits CharSize) const { /// getTypeSizeInChars - Return the size of the specified type, in characters. /// This method does not work on incomplete types. CharUnits ASTContext::getTypeSizeInChars(QualType T) const { - return toCharUnitsFromBits(getTypeSize(T)); + return getTypeInfoInChars(T).first; } CharUnits ASTContext::getTypeSizeInChars(const Type *T) const { - return toCharUnitsFromBits(getTypeSize(T)); + return getTypeInfoInChars(T).first; } /// getTypeAlignInChars - Return the ABI-specified alignment of a type, in @@ -1718,6 +1758,9 @@ CharUnits ASTContext::getTypeAlignInChars(const Type *T) const { unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { unsigned ABIAlign = getTypeAlign(T); + if (Target->getTriple().getArch() == llvm::Triple::xcore) + return ABIAlign; // Never overalign on XCore. + // Double and long long should be naturally aligned if possible. if (const ComplexType* CT = T->getAs<ComplexType>()) T = CT->getElementType().getTypePtr(); @@ -2042,10 +2085,7 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, const FunctionProtoType *FPT = cast<FunctionProtoType>(T); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = Info; - Result = getFunctionType(FPT->getResultType(), - ArrayRef<QualType>(FPT->arg_type_begin(), - FPT->getNumArgs()), - EPI); + Result = getFunctionType(FPT->getResultType(), FPT->getArgTypes(), EPI); } return cast<FunctionType>(Result.getTypePtr()); @@ -2053,12 +2093,18 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType) { - // FIXME: Need to inform serialization code about this! - for (FD = FD->getMostRecentDecl(); FD; FD = FD->getPreviousDecl()) { + FD = FD->getMostRecentDecl(); + while (true) { const FunctionProtoType *FPT = FD->getType()->castAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); FD->setType(getFunctionType(ResultType, FPT->getArgTypes(), EPI)); + if (FunctionDecl *Next = FD->getPreviousDecl()) + FD = Next; + else + break; } + if (ASTMutationListener *L = getASTMutationListener()) + L->DeducedReturnType(FD, ResultType); } /// getComplexType - Return the uniqued reference to the type for a complex @@ -2117,6 +2163,45 @@ QualType ASTContext::getPointerType(QualType T) const { return QualType(New, 0); } +QualType ASTContext::getDecayedType(QualType T) const { + assert((T->isArrayType() || T->isFunctionType()) && "T does not decay"); + + llvm::FoldingSetNodeID ID; + DecayedType::Profile(ID, T); + void *InsertPos = 0; + if (DecayedType *DT = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(DT, 0); + + QualType Decayed; + + // C99 6.7.5.3p7: + // A declaration of a parameter as "array of type" shall be + // adjusted to "qualified pointer to type", where the type + // qualifiers (if any) are those specified within the [ and ] of + // the array type derivation. + if (T->isArrayType()) + Decayed = getArrayDecayedType(T); + + // C99 6.7.5.3p8: + // A declaration of a parameter as "function returning type" + // shall be adjusted to "pointer to function returning type", as + // in 6.3.2.1. + if (T->isFunctionType()) + Decayed = getPointerType(T); + + QualType Canonical = getCanonicalType(Decayed); + + // Get the new insert position for the node we care about. + DecayedType *NewIP = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + + DecayedType *New = + new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical); + Types.push_back(New); + DecayedTypes.InsertNode(New, InsertPos); + return QualType(New, 0); +} + /// getBlockPointerType - Return the uniqued reference to the type for /// a pointer to the specified block. QualType ASTContext::getBlockPointerType(QualType T) const { @@ -2676,9 +2761,8 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType, QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const { - const CallingConv DefaultCC = Info.getCC(); - const CallingConv CallConv = (LangOpts.MRTD && DefaultCC == CC_Default) ? - CC_X86StdCall : DefaultCC; + const CallingConv CallConv = Info.getCC(); + // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; @@ -2690,11 +2774,8 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, return QualType(FT, 0); QualType Canonical; - if (!ResultTy.isCanonical() || - getCanonicalCallConv(CallConv) != CallConv) { - Canonical = - getFunctionNoProtoType(getCanonicalType(ResultTy), - Info.withCallingConv(getCanonicalCallConv(CallConv))); + if (!ResultTy.isCanonical()) { + Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), Info); // Get the new insert position for the node we care about. FunctionNoProtoType *NewIP = @@ -2743,14 +2824,10 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; - const CallingConv DefaultCC = EPI.ExtInfo.getCC(); - const CallingConv CallConv = (LangOpts.MRTD && DefaultCC == CC_Default) ? - CC_X86StdCall : DefaultCC; - // If this type isn't canonical, get the canonical version of it. // The exception spec is not part of the canonical type. QualType Canonical; - if (!isCanonical || getCanonicalCallConv(CallConv) != CallConv) { + if (!isCanonical) { SmallVector<QualType, 16> CanonicalArgs; CanonicalArgs.reserve(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) @@ -2760,8 +2837,6 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, CanonicalEPI.HasTrailingReturn = false; CanonicalEPI.ExceptionSpecType = EST_None; CanonicalEPI.NumExceptions = 0; - CanonicalEPI.ExtInfo - = CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv)); // Result types do not have ARC lifetime qualifiers. QualType CanResultTy = getCanonicalType(ResultTy); @@ -2803,7 +2878,6 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; - newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv); new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI); Types.push_back(FTP); FunctionProtoTypes.InsertNode(FTP, InsertPos); @@ -2856,13 +2930,11 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { "Template type parameter types are always available."); if (const RecordDecl *Record = dyn_cast<RecordDecl>(Decl)) { - assert(!Record->getPreviousDecl() && - "struct/union has previous declaration"); + assert(Record->isFirstDecl() && "struct/union has previous declaration"); assert(!NeedsInjectedClassNameType(Record)); return getRecordType(Record); } else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) { - assert(!Enum->getPreviousDecl() && - "enum has previous declaration"); + assert(Enum->isFirstDecl() && "enum has previous declaration"); return getEnumType(Enum); } else if (const UnresolvedUsingTypenameDecl *Using = dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) { @@ -4104,22 +4176,9 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { } QualType ASTContext::getAdjustedParameterType(QualType T) const { - // C99 6.7.5.3p7: - // A declaration of a parameter as "array of type" shall be - // adjusted to "qualified pointer to type", where the type - // qualifiers (if any) are those specified within the [ and ] of - // the array type derivation. - if (T->isArrayType()) - return getArrayDecayedType(T); - - // C99 6.7.5.3p8: - // A declaration of a parameter as "function returning type" - // shall be adjusted to "pointer to function returning type", as - // in 6.3.2.1. - if (T->isFunctionType()) - return getPointerType(T); - - return T; + if (T->isArrayType() || T->isFunctionType()) + return getDecayedType(T); + return T; } QualType ASTContext::getSignatureParameterType(QualType T) const { @@ -4364,12 +4423,27 @@ Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const { return Qualifiers::OCL_None; } +static const Type *getIntegerTypeForEnum(const EnumType *ET) { + // Incomplete enum types are not treated as integer types. + // FIXME: In C++, enum types are never integer types. + if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped()) + return ET->getDecl()->getIntegerType().getTypePtr(); + return NULL; +} + /// getIntegerTypeOrder - Returns the highest ranked integer type: /// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If /// LHS < RHS, return -1. int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const { const Type *LHSC = getCanonicalType(LHS).getTypePtr(); const Type *RHSC = getCanonicalType(RHS).getTypePtr(); + + // Unwrap enums to their underlying type. + if (const EnumType *ET = dyn_cast<EnumType>(LHSC)) + LHSC = getIntegerTypeForEnum(ET); + if (const EnumType *ET = dyn_cast<EnumType>(RHSC)) + RHSC = getIntegerTypeForEnum(ET); + if (LHSC == RHSC) return 0; bool LHSUnsigned = LHSC->isUnsignedIntegerType(); @@ -4484,7 +4558,7 @@ QualType ASTContext::getBlockDescriptorType() const { UnsignedLongTy, }; - const char *FieldNames[] = { + static const char *const FieldNames[] = { "reserved", "Size" }; @@ -4525,7 +4599,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { getPointerType(VoidPtrTy) }; - const char *FieldNames[] = { + static const char *const FieldNames[] = { "reserved", "Size", "CopyFuncPtr", @@ -4910,6 +4984,10 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, if (PD->isReadOnly()) { S += ",R"; + if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) + S += ",C"; + if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) + S += ",&"; } else { switch (PD->getSetterKind()) { case ObjCPropertyDecl::Assign: break; @@ -5200,12 +5278,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } else { S += '['; - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { - if (getTypeSize(CAT->getElementType()) == 0) - S += '0'; - else - S += llvm::utostr(CAT->getSize().getZExtValue()); - } else { + if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) + S += llvm::utostr(CAT->getSize().getZExtValue()); + else { //Variable length arrays are encoded as a regular array with 0 elements. assert((isa<VariableArrayType>(AT) || isa<IncompleteArrayType>(AT)) && "Unknown array type!"); @@ -5384,6 +5459,20 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // We encode the underlying type which comes out as // {...}; S += '^'; + if (FD && OPT->getInterfaceDecl()) { + // Prevent recursive encoding of fields in some rare cases. + ObjCInterfaceDecl *OI = OPT->getInterfaceDecl(); + SmallVector<const ObjCIvarDecl*, 32> Ivars; + DeepCollectObjCIvars(OI, true, Ivars); + for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { + if (cast<FieldDecl>(Ivars[i]) == FD) { + S += '{'; + S += OI->getIdentifier()->getName(); + S += '}'; + return; + } + } + } getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures, NULL, @@ -5484,7 +5573,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (base->isEmpty()) continue; uint64_t offs = toBits(layout.getVBaseClassOffset(base)); - if (FieldOrBaseOffsets.find(offs) == FieldOrBaseOffsets.end()) + if (offs >= uint64_t(toBits(layout.getNonVirtualSize())) && + FieldOrBaseOffsets.find(offs) == FieldOrBaseOffsets.end()) FieldOrBaseOffsets.insert(FieldOrBaseOffsets.end(), std::make_pair(offs, base)); } @@ -6267,6 +6357,8 @@ ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, CanQualType ASTContext::getFromTargetType(unsigned Type) const { switch (Type) { case TargetInfo::NoInt: return CanQualType(); + case TargetInfo::SignedChar: return SignedCharTy; + case TargetInfo::UnsignedChar: return UnsignedCharTy; case TargetInfo::SignedShort: return ShortTy; case TargetInfo::UnsignedShort: return UnsignedShortTy; case TargetInfo::SignedInt: return IntTy; @@ -6369,15 +6461,6 @@ ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, return false; } -/// QualifiedIdConformsQualifiedId - compare id<pr,...> with id<pr1,...> -/// return true if lhs's protocols conform to rhs's protocol; false -/// otherwise. -bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) { - if (lhs->isObjCQualifiedIdType() && rhs->isObjCQualifiedIdType()) - return ObjCQualifiedIdTypesAreCompatible(lhs, rhs, false); - return false; -} - /// ObjCQualifiedClassTypesAreCompatible - compare Class<pr,...> and /// Class<pr1, ...>. bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs, @@ -6890,7 +6973,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionType::ExtInfo rbaseInfo = rbase->getExtInfo(); // Compatible functions must have compatible calling conventions - if (!isSameCallConv(lbaseInfo.getCC(), rbaseInfo.getCC())) + if (lbaseInfo.getCC() != rbaseInfo.getCC()) return QualType(); // Regparm is part of the calling convention. @@ -7000,10 +7083,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionProtoType::ExtProtoInfo EPI = proto->getExtProtoInfo(); EPI.ExtInfo = einfo; - return getFunctionType(retType, - ArrayRef<QualType>(proto->arg_type_begin(), - proto->getNumArgs()), - EPI); + return getFunctionType(retType, proto->getArgTypes(), EPI); } if (allLTypes) return lhs; @@ -7351,11 +7431,8 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { if (const FunctionProtoType *FPT = cast<FunctionProtoType>(F)) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = getFunctionExtInfo(LHS); - QualType ResultType - = getFunctionType(OldReturnType, - ArrayRef<QualType>(FPT->arg_type_begin(), - FPT->getNumArgs()), - EPI); + QualType ResultType = + getFunctionType(OldReturnType, FPT->getArgTypes(), EPI); return ResultType; } } @@ -7407,7 +7484,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { //===----------------------------------------------------------------------===// unsigned ASTContext::getIntWidth(QualType T) const { - if (const EnumType *ET = dyn_cast<EnumType>(T)) + if (const EnumType *ET = T->getAs<EnumType>()) T = ET->getDecl()->getIntegerType(); if (T->isBooleanType()) return 1; @@ -7450,6 +7527,8 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { ASTMutationListener::~ASTMutationListener() { } +void ASTMutationListener::DeducedReturnType(const FunctionDecl *FD, + QualType ReturnType) {} //===----------------------------------------------------------------------===// // Builtin Type Computation @@ -7507,6 +7586,11 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, "Bad modifiers used with 'v'!"); Type = Context.VoidTy; break; + case 'h': + assert(HowLong == 0 && !Signed && !Unsigned && + "Bad modifiers used with 'f'!"); + Type = Context.HalfTy; + break; case 'f': assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers used with 'f'!"); @@ -7734,7 +7818,7 @@ QualType ASTContext::GetBuiltinType(unsigned Id, assert((TypeStr[0] != '.' || TypeStr[1] == 0) && "'.' should only occur at end of builtin type list!"); - FunctionType::ExtInfo EI; + FunctionType::ExtInfo EI(CC_C); if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true); bool Variadic = (TypeStr[0] == '.'); @@ -7751,36 +7835,30 @@ QualType ASTContext::GetBuiltinType(unsigned Id, } GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { - GVALinkage External = GVA_StrongExternal; - - Linkage L = FD->getLinkage(); - switch (L) { - case NoLinkage: - case InternalLinkage: - case UniqueExternalLinkage: + if (!FD->isExternallyVisible()) return GVA_Internal; - - case ExternalLinkage: - switch (FD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - External = GVA_StrongExternal; - break; - case TSK_ExplicitInstantiationDefinition: - return GVA_ExplicitTemplateInstantiation; + GVALinkage External = GVA_StrongExternal; + switch (FD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + External = GVA_StrongExternal; + break; - case TSK_ExplicitInstantiationDeclaration: - case TSK_ImplicitInstantiation: - External = GVA_TemplateInstantiation; - break; - } + case TSK_ExplicitInstantiationDefinition: + return GVA_ExplicitTemplateInstantiation; + + case TSK_ExplicitInstantiationDeclaration: + case TSK_ImplicitInstantiation: + External = GVA_TemplateInstantiation; + break; } if (!FD->isInlined()) return External; - - if (!getLangOpts().CPlusPlus || FD->hasAttr<GNUInlineAttr>()) { + + if ((!getLangOpts().CPlusPlus && !getLangOpts().MicrosoftMode) || + FD->hasAttr<GNUInlineAttr>()) { // GNU or C99 inline semantics. Determine whether this symbol should be // externally visible. if (FD->isInlineDefinitionExternallyVisible()) @@ -7804,37 +7882,23 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { } GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { - // If this is a static data member, compute the kind of template - // specialization. Otherwise, this variable is not part of a - // template. - TemplateSpecializationKind TSK = TSK_Undeclared; - if (VD->isStaticDataMember()) - TSK = VD->getTemplateSpecializationKind(); - - Linkage L = VD->getLinkage(); - - switch (L) { - case NoLinkage: - case InternalLinkage: - case UniqueExternalLinkage: + if (!VD->isExternallyVisible()) return GVA_Internal; - case ExternalLinkage: - switch (TSK) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - return GVA_StrongExternal; + switch (VD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + return GVA_StrongExternal; - case TSK_ExplicitInstantiationDeclaration: - llvm_unreachable("Variable should not be instantiated"); - // Fall through to treat this like any other instantiation. - - case TSK_ExplicitInstantiationDefinition: - return GVA_ExplicitTemplateInstantiation; + case TSK_ExplicitInstantiationDeclaration: + llvm_unreachable("Variable should not be instantiated"); + // Fall through to treat this like any other instantiation. - case TSK_ImplicitInstantiation: - return GVA_TemplateInstantiation; - } + case TSK_ExplicitInstantiationDefinition: + return GVA_ExplicitTemplateInstantiation; + + case TSK_ImplicitInstantiation: + return GVA_TemplateInstantiation; } llvm_unreachable("Invalid Linkage!"); @@ -7918,16 +7982,13 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return false; } -CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) { +CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, + bool IsCXXMethod) const { // Pass through to the C++ ABI object - return ABI->getDefaultMethodCallConv(isVariadic); -} + if (IsCXXMethod) + return ABI->getDefaultMethodCallConv(IsVariadic); -CallingConv ASTContext::getCanonicalCallConv(CallingConv CC) const { - if (CC == CC_C && !LangOpts.MRTD && - getTargetInfo().getCXXABI().isMemberFunctionCCDefault()) - return CC_Default; - return CC; + return (LangOpts.MRTD && !IsVariadic) ? CC_X86StdCall : CC_C; } bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { @@ -7941,9 +8002,9 @@ MangleContext *ASTContext::createMangleContext() { case TargetCXXABI::GenericItanium: case TargetCXXABI::GenericARM: case TargetCXXABI::iOS: - return createItaniumMangleContext(*this, getDiagnostics()); + return ItaniumMangleContext::create(*this, getDiagnostics()); case TargetCXXABI::Microsoft: - return createMicrosoftMangleContext(*this, getDiagnostics()); + return MicrosoftMangleContext::create(*this, getDiagnostics()); } llvm_unreachable("Unsupported ABI"); } @@ -7951,45 +8012,77 @@ MangleContext *ASTContext::createMangleContext() { CXXABI::~CXXABI() {} size_t ASTContext::getSideTableAllocatedMemory() const { - return ASTRecordLayouts.getMemorySize() - + llvm::capacity_in_bytes(ObjCLayouts) - + llvm::capacity_in_bytes(KeyFunctions) - + llvm::capacity_in_bytes(ObjCImpls) - + llvm::capacity_in_bytes(BlockVarCopyInits) - + llvm::capacity_in_bytes(DeclAttrs) - + llvm::capacity_in_bytes(InstantiatedFromStaticDataMember) - + llvm::capacity_in_bytes(InstantiatedFromUsingDecl) - + llvm::capacity_in_bytes(InstantiatedFromUsingShadowDecl) - + llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl) - + llvm::capacity_in_bytes(OverriddenMethods) - + llvm::capacity_in_bytes(Types) - + llvm::capacity_in_bytes(VariableArrayTypes) - + llvm::capacity_in_bytes(ClassScopeSpecializationPattern); -} - -void ASTContext::addUnnamedTag(const TagDecl *Tag) { - // FIXME: This mangling should be applied to function local classes too - if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl() || - !isa<CXXRecordDecl>(Tag->getParent()) || Tag->getLinkage() != ExternalLinkage) - return; + return ASTRecordLayouts.getMemorySize() + + llvm::capacity_in_bytes(ObjCLayouts) + + llvm::capacity_in_bytes(KeyFunctions) + + llvm::capacity_in_bytes(ObjCImpls) + + llvm::capacity_in_bytes(BlockVarCopyInits) + + llvm::capacity_in_bytes(DeclAttrs) + + llvm::capacity_in_bytes(TemplateOrInstantiation) + + llvm::capacity_in_bytes(InstantiatedFromUsingDecl) + + llvm::capacity_in_bytes(InstantiatedFromUsingShadowDecl) + + llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl) + + llvm::capacity_in_bytes(OverriddenMethods) + + llvm::capacity_in_bytes(Types) + + llvm::capacity_in_bytes(VariableArrayTypes) + + llvm::capacity_in_bytes(ClassScopeSpecializationPattern); +} + +/// getIntTypeForBitwidth - +/// sets integer QualTy according to specified details: +/// bitwidth, signed/unsigned. +/// Returns empty type if there is no appropriate target types. +QualType ASTContext::getIntTypeForBitwidth(unsigned DestWidth, + unsigned Signed) const { + TargetInfo::IntType Ty = getTargetInfo().getIntTypeByWidth(DestWidth, Signed); + CanQualType QualTy = getFromTargetType(Ty); + if (!QualTy && DestWidth == 128) + return Signed ? Int128Ty : UnsignedInt128Ty; + return QualTy; +} + +/// getRealTypeForBitwidth - +/// sets floating point QualTy according to specified bitwidth. +/// Returns empty type if there is no appropriate target types. +QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth) const { + TargetInfo::RealType Ty = getTargetInfo().getRealTypeByWidth(DestWidth); + switch (Ty) { + case TargetInfo::Float: + return FloatTy; + case TargetInfo::Double: + return DoubleTy; + case TargetInfo::LongDouble: + return LongDoubleTy; + case TargetInfo::NoFloat: + return QualType(); + } - std::pair<llvm::DenseMap<const DeclContext *, unsigned>::iterator, bool> P = - UnnamedMangleContexts.insert(std::make_pair(Tag->getParent(), 0)); - UnnamedMangleNumbers.insert(std::make_pair(Tag, P.first->second++)); + llvm_unreachable("Unhandled TargetInfo::RealType value"); } -int ASTContext::getUnnamedTagManglingNumber(const TagDecl *Tag) const { - llvm::DenseMap<const TagDecl *, unsigned>::const_iterator I = - UnnamedMangleNumbers.find(Tag); - return I != UnnamedMangleNumbers.end() ? I->second : -1; +void ASTContext::setManglingNumber(const NamedDecl *ND, unsigned Number) { + if (Number > 1) + MangleNumbers[ND] = Number; } -unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) { - CXXRecordDecl *Lambda = CallOperator->getParent(); - return LambdaMangleContexts[Lambda->getDeclContext()] - .getManglingNumber(CallOperator); +unsigned ASTContext::getManglingNumber(const NamedDecl *ND) const { + llvm::DenseMap<const NamedDecl *, unsigned>::const_iterator I = + MangleNumbers.find(ND); + return I != MangleNumbers.end() ? I->second : 1; } +MangleNumberingContext & +ASTContext::getManglingNumberContext(const DeclContext *DC) { + assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C. + MangleNumberingContext *&MCtx = MangleNumberingContexts[DC]; + if (!MCtx) + MCtx = createMangleNumberingContext(); + return *MCtx; +} + +MangleNumberingContext *ASTContext::createMangleNumberingContext() const { + return ABI->createMangleNumberingContext(); +} void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) { ParamIndices[D] = index; @@ -8001,3 +8094,160 @@ unsigned ASTContext::getParameterIndex(const ParmVarDecl *D) const { "ParmIndices lacks entry set by ParmVarDecl"); return I->second; } + +APValue * +ASTContext::getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, + bool MayCreate) { + assert(E && E->getStorageDuration() == SD_Static && + "don't need to cache the computed value for this temporary"); + if (MayCreate) + return &MaterializedTemporaryValues[E]; + + llvm::DenseMap<const MaterializeTemporaryExpr *, APValue>::iterator I = + MaterializedTemporaryValues.find(E); + return I == MaterializedTemporaryValues.end() ? 0 : &I->second; +} + +bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { + const llvm::Triple &T = getTargetInfo().getTriple(); + if (!T.isOSDarwin()) + return false; + + if (!(T.isiOS() && T.isOSVersionLT(7)) && + !(T.isMacOSX() && T.isOSVersionLT(10, 9))) + return false; + + QualType AtomicTy = E->getPtr()->getType()->getPointeeType(); + CharUnits sizeChars = getTypeSizeInChars(AtomicTy); + uint64_t Size = sizeChars.getQuantity(); + CharUnits alignChars = getTypeAlignInChars(AtomicTy); + unsigned Align = alignChars.getQuantity(); + unsigned MaxInlineWidthInBits = getTargetInfo().getMaxAtomicInlineWidth(); + return (Size != Align || toBits(sizeChars) > MaxInlineWidthInBits); +} + +namespace { + + /// \brief A \c RecursiveASTVisitor that builds a map from nodes to their + /// parents as defined by the \c RecursiveASTVisitor. + /// + /// Note that the relationship described here is purely in terms of AST + /// traversal - there are other relationships (for example declaration context) + /// in the AST that are better modeled by special matchers. + /// + /// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes. + class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> { + + public: + /// \brief Builds and returns the translation unit's parent map. + /// + /// The caller takes ownership of the returned \c ParentMap. + static ASTContext::ParentMap *buildMap(TranslationUnitDecl &TU) { + ParentMapASTVisitor Visitor(new ASTContext::ParentMap); + Visitor.TraverseDecl(&TU); + return Visitor.Parents; + } + + private: + typedef RecursiveASTVisitor<ParentMapASTVisitor> VisitorBase; + + ParentMapASTVisitor(ASTContext::ParentMap *Parents) : Parents(Parents) { + } + + bool shouldVisitTemplateInstantiations() const { + return true; + } + bool shouldVisitImplicitCode() const { + return true; + } + // Disables data recursion. We intercept Traverse* methods in the RAV, which + // are not triggered during data recursion. + bool shouldUseDataRecursionFor(clang::Stmt *S) const { + return false; + } + + template <typename T> + bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) { + if (Node == NULL) + return true; + if (ParentStack.size() > 0) + // FIXME: Currently we add the same parent multiple times, for example + // when we visit all subexpressions of template instantiations; this is + // suboptimal, bug benign: the only way to visit those is with + // hasAncestor / hasParent, and those do not create new matches. + // The plan is to enable DynTypedNode to be storable in a map or hash + // map. The main problem there is to implement hash functions / + // comparison operators for all types that DynTypedNode supports that + // do not have pointer identity. + (*Parents)[Node].push_back(ParentStack.back()); + ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node)); + bool Result = (this ->* traverse) (Node); + ParentStack.pop_back(); + return Result; + } + + bool TraverseDecl(Decl *DeclNode) { + return TraverseNode(DeclNode, &VisitorBase::TraverseDecl); + } + + bool TraverseStmt(Stmt *StmtNode) { + return TraverseNode(StmtNode, &VisitorBase::TraverseStmt); + } + + ASTContext::ParentMap *Parents; + llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack; + + friend class RecursiveASTVisitor<ParentMapASTVisitor>; + }; + +} // end namespace + +ASTContext::ParentVector +ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { + assert(Node.getMemoizationData() && + "Invariant broken: only nodes that support memoization may be " + "used in the parent map."); + if (!AllParents) { + // We always need to run over the whole translation unit, as + // hasAncestor can escape any subtree. + AllParents.reset( + ParentMapASTVisitor::buildMap(*getTranslationUnitDecl())); + } + ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData()); + if (I == AllParents->end()) { + return ParentVector(); + } + return I->second; +} + +bool +ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, + const ObjCMethodDecl *MethodImpl) { + // No point trying to match an unavailable/deprecated mothod. + if (MethodDecl->hasAttr<UnavailableAttr>() + || MethodDecl->hasAttr<DeprecatedAttr>()) + return false; + if (MethodDecl->getObjCDeclQualifier() != + MethodImpl->getObjCDeclQualifier()) + return false; + if (!hasSameType(MethodDecl->getResultType(), + MethodImpl->getResultType())) + return false; + + if (MethodDecl->param_size() != MethodImpl->param_size()) + return false; + + for (ObjCMethodDecl::param_const_iterator IM = MethodImpl->param_begin(), + IF = MethodDecl->param_begin(), EM = MethodImpl->param_end(), + EF = MethodDecl->param_end(); + IM != EM && IF != EF; ++IM, ++IF) { + const ParmVarDecl *DeclVar = (*IF); + const ParmVarDecl *ImplVar = (*IM); + if (ImplVar->getObjCDeclQualifier() != DeclVar->getObjCDeclQualifier()) + return false; + if (!hasSameType(DeclVar->getType(), ImplVar->getType())) + return false; + } + return (MethodDecl->isVariadic() == MethodImpl->isVariadic()); + +} |