diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
52 files changed, 7421 insertions, 5182 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp index 541836b21b..0fa0216 100644 --- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp +++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp @@ -34,7 +34,7 @@ namespace { struct APValue::LV : LVBase { static const unsigned InlinePathSpace = - (MaxSize - sizeof(LVBase)) / sizeof(LValuePathEntry); + (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry); /// Path - The sequence of base classes, fields and array indices to follow to /// walk from Base to the subobject. When performing GCC-style folding, there @@ -75,7 +75,7 @@ namespace { struct APValue::MemberPointerData : MemberPointerBase { static const unsigned InlinePathSpace = - (MaxSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); + (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); typedef const CXXRecordDecl *PathElem; union { PathElem Path[InlinePathSpace]; @@ -117,7 +117,7 @@ APValue::StructData::~StructData() { delete [] Elts; } -APValue::UnionData::UnionData() : Field(0), Value(new APValue) {} +APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {} APValue::UnionData::~UnionData () { delete Value; } @@ -136,7 +136,7 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { break; case Vector: MakeVector(); - setVector(((const Vec *)(const char *)RHS.Data)->Elts, + setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, RHS.getVectorLength()); break; case ComplexInt: @@ -188,27 +188,27 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { void APValue::DestroyDataAndMakeUninit() { if (Kind == Int) - ((APSInt*)(char*)Data)->~APSInt(); + ((APSInt*)(char*)Data.buffer)->~APSInt(); else if (Kind == Float) - ((APFloat*)(char*)Data)->~APFloat(); + ((APFloat*)(char*)Data.buffer)->~APFloat(); else if (Kind == Vector) - ((Vec*)(char*)Data)->~Vec(); + ((Vec*)(char*)Data.buffer)->~Vec(); else if (Kind == ComplexInt) - ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt(); + ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt(); else if (Kind == ComplexFloat) - ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat(); + ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat(); else if (Kind == LValue) - ((LV*)(char*)Data)->~LV(); + ((LV*)(char*)Data.buffer)->~LV(); else if (Kind == Array) - ((Arr*)(char*)Data)->~Arr(); + ((Arr*)(char*)Data.buffer)->~Arr(); else if (Kind == Struct) - ((StructData*)(char*)Data)->~StructData(); + ((StructData*)(char*)Data.buffer)->~StructData(); else if (Kind == Union) - ((UnionData*)(char*)Data)->~UnionData(); + ((UnionData*)(char*)Data.buffer)->~UnionData(); else if (Kind == MemberPointer) - ((MemberPointerData*)(char*)Data)->~MemberPointerData(); + ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData(); else if (Kind == AddrLabelDiff) - ((AddrLabelDiffData*)(char*)Data)->~AddrLabelDiffData(); + ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData(); Kind = Uninitialized; } @@ -239,19 +239,20 @@ bool APValue::needsCleanup() const { "same size."); return getComplexIntReal().needsCleanup(); case LValue: - return reinterpret_cast<const LV *>(Data)->hasPathPtr(); + return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr(); case MemberPointer: - return reinterpret_cast<const MemberPointerData *>(Data)->hasPathPtr(); + return reinterpret_cast<const MemberPointerData *>(Data.buffer) + ->hasPathPtr(); } llvm_unreachable("Unknown APValue kind!"); } void APValue::swap(APValue &RHS) { std::swap(Kind, RHS.Kind); - char TmpData[MaxSize]; - memcpy(TmpData, Data, MaxSize); - memcpy(Data, RHS.Data, MaxSize); - memcpy(RHS.Data, TmpData, MaxSize); + char TmpData[DataSize]; + memcpy(TmpData, Data.buffer, DataSize); + memcpy(Data.buffer, RHS.Data.buffer, DataSize); + memcpy(RHS.Data.buffer, TmpData, DataSize); } void APValue::dump() const { @@ -402,8 +403,13 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) Out << *VD; - else - Base.get<const Expr*>()->printPretty(Out, 0, Ctx.getPrintingPolicy()); + else { + assert(Base.get<const Expr *>() != nullptr && + "Expecting non-null Expr"); + Base.get<const Expr*>()->printPretty(Out, nullptr, + Ctx.getPrintingPolicy()); + } + if (!O.isZero()) { Out << " + " << (O / S); if (IsReference) @@ -424,12 +430,13 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ ElemTy = VD->getType(); } else { const Expr *E = Base.get<const Expr*>(); - E->printPretty(Out, 0, Ctx.getPrintingPolicy()); + assert(E != nullptr && "Expecting non-null Expr"); + E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); ElemTy = E->getType(); } ArrayRef<LValuePathEntry> Path = getLValuePath(); - const CXXRecordDecl *CastToBase = 0; + const CXXRecordDecl *CastToBase = nullptr; for (unsigned I = 0, N = Path.size(); I != N; ++I) { if (ElemTy->getAs<RecordType>()) { // The lvalue refers to a class type, so the next path entry is a base @@ -498,8 +505,7 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ First = false; } } - for (RecordDecl::field_iterator FI = RD->field_begin(); - FI != RD->field_end(); ++FI) { + for (const auto *FI : RD->fields()) { if (!First) Out << ", "; if (FI->isUnnamedBitfield()) continue; @@ -546,39 +552,39 @@ std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { const APValue::LValueBase APValue::getLValueBase() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getPointer(); + return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getPointer(); } bool APValue::isLValueOnePastTheEnd() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getInt(); + return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getInt(); } CharUnits &APValue::getLValueOffset() { assert(isLValue() && "Invalid accessor"); - return ((LV*)(void*)Data)->Offset; + return ((LV*)(void*)Data.buffer)->Offset; } bool APValue::hasLValuePath() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const char*)Data)->hasPath(); + return ((const LV*)(const char*)Data.buffer)->hasPath(); } ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { assert(isLValue() && hasLValuePath() && "Invalid accessor"); - const LV &LVal = *((const LV*)(const char*)Data); + const LV &LVal = *((const LV*)(const char*)Data.buffer); return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength); } unsigned APValue::getLValueCallIndex() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const char*)Data)->CallIndex; + return ((const LV*)(const char*)Data.buffer)->CallIndex; } void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, unsigned CallIndex) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data); + LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); LVal.BaseAndIsOnePastTheEnd.setInt(false); LVal.Offset = O; @@ -590,7 +596,7 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, unsigned CallIndex) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data); + LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd); LVal.Offset = O; @@ -601,39 +607,42 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, const ValueDecl *APValue::getMemberPointerDecl() const { assert(isMemberPointer() && "Invalid accessor"); - const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); return MPD.MemberAndIsDerivedMember.getPointer(); } bool APValue::isMemberPointerToDerivedMember() const { assert(isMemberPointer() && "Invalid accessor"); - const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); return MPD.MemberAndIsDerivedMember.getInt(); } ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { assert(isMemberPointer() && "Invalid accessor"); - const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength); } void APValue::MakeLValue() { assert(isUninit() && "Bad state change"); - assert(sizeof(LV) <= MaxSize && "LV too big"); - new ((void*)(char*)Data) LV(); + static_assert(sizeof(LV) <= DataSize, "LV too big"); + new ((void*)(char*)Data.buffer) LV(); Kind = LValue; } void APValue::MakeArray(unsigned InitElts, unsigned Size) { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) Arr(InitElts, Size); + new ((void*)(char*)Data.buffer) Arr(InitElts, Size); Kind = Array; } void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, ArrayRef<const CXXRecordDecl*> Path) { assert(isUninit() && "Bad state change"); - MemberPointerData *MPD = new ((void*)(char*)Data) MemberPointerData; + MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; Kind = MemberPointer; MPD->MemberAndIsDerivedMember.setPointer(Member); MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index a03cf9e7..bccdae9 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -29,6 +29,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" +#include "clang/AST/VTableBuilder.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -62,6 +63,13 @@ enum FloatingRank { RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { if (!CommentsLoaded && ExternalSource) { ExternalSource->ReadComments(); + +#ifndef NDEBUG + ArrayRef<RawComment *> RawComments = Comments.getComments(); + assert(std::is_sorted(RawComments.begin(), RawComments.end(), + BeforeThanCompare<RawComment>(SourceMgr))); +#endif + CommentsLoaded = true; } @@ -69,23 +77,23 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // User can not attach documentation to implicit declarations. if (D->isImplicit()) - return NULL; + return nullptr; // User can not attach documentation to implicit instantiations. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) - return NULL; + return nullptr; } if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->isStaticDataMember() && VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) - return NULL; + return nullptr; } if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { if (CRD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) - return NULL; + return nullptr; } if (const ClassTemplateSpecializationDecl *CTSD = @@ -93,35 +101,35 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { TemplateSpecializationKind TSK = CTSD->getSpecializationKind(); if (TSK == TSK_ImplicitInstantiation || TSK == TSK_Undeclared) - return NULL; + return nullptr; } if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) { if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) - return NULL; + return nullptr; } if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { // When tag declaration (but not definition!) is part of the // decl-specifier-seq of some other declaration, it doesn't get comment if (TD->isEmbeddedInDeclarator() && !TD->isCompleteDefinition()) - return NULL; + return nullptr; } // TODO: handle comments for function parameters properly. if (isa<ParmVarDecl>(D)) - return NULL; + return nullptr; // TODO: we could look up template parameter documentation in the template // documentation. if (isa<TemplateTypeParmDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTemplateParmDecl>(D)) - return NULL; + return nullptr; ArrayRef<RawComment *> RawComments = Comments.getComments(); // If there are no comments anywhere, we won't find anything. if (RawComments.empty()) - return NULL; + return nullptr; // Find declaration location. // For Objective-C declarations we generally don't expect to have multiple @@ -137,17 +145,29 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { DeclLoc = D->getLocStart(); 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 (DeclLoc.isMacroID()) { + if (isa<TypedefDecl>(D)) { + // 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". + DeclLoc = D->getLocStart(); + } else if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { + // If location of the tag decl is inside a macro, but the spelling of + // the tag name comes from a macro argument, it looks like a special + // macro like NS_ENUM is being used to define the tag decl. In that + // case, adjust the source location to the expansion loc so that we can + // attach the comment to the tag decl. + if (SourceMgr.isMacroArgExpansion(DeclLoc) && + TD->isCompleteDefinition()) + DeclLoc = SourceMgr.getExpansionLoc(DeclLoc); + } + } } // If the declaration doesn't map directly to a location in a file, we // can't find the comment. if (DeclLoc.isInvalid() || !DeclLoc.isFileID()) - return NULL; + return nullptr; // Find the comment that occurs just after this declaration. ArrayRef<RawComment *>::iterator Comment; @@ -201,12 +221,12 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // The comment just after the declaration was not a trailing comment. // Let's look at the previous comment. if (Comment == RawComments.begin()) - return NULL; + return nullptr; --Comment; // Check that we actually have a non-member Doxygen comment. if (!(*Comment)->isDocumentation() || (*Comment)->isTrailingComment()) - return NULL; + return nullptr; // Decompose the end of the comment. std::pair<FileID, unsigned> CommentEndDecomp @@ -215,14 +235,14 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // If the comment and the declaration aren't in the same file, then they // aren't related. if (DeclLocDecomp.first != CommentEndDecomp.first) - return NULL; + return nullptr; // Get the corresponding buffer. bool Invalid = false; const char *Buffer = SourceMgr.getBufferData(DeclLocDecomp.first, &Invalid).data(); if (Invalid) - return NULL; + return nullptr; // Extract text between the comment and declaration. StringRef Text(Buffer + CommentEndDecomp.second, @@ -231,7 +251,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) - return NULL; + return nullptr; return *Comment; } @@ -329,13 +349,11 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( } // Search for comments attached to declarations in the redeclaration chain. - const RawComment *RC = NULL; - const Decl *OriginalDeclForRC = NULL; - for (Decl::redecl_iterator I = D->redecls_begin(), - E = D->redecls_end(); - I != E; ++I) { + const RawComment *RC = nullptr; + const Decl *OriginalDeclForRC = nullptr; + for (auto I : D->redecls()) { llvm::DenseMap<const Decl *, RawCommentAndCacheFlags>::iterator Pos = - RedeclComments.find(*I); + RedeclComments.find(I); if (Pos != RedeclComments.end()) { const RawCommentAndCacheFlags &Raw = Pos->second; if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) { @@ -344,16 +362,16 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( break; } } else { - RC = getRawCommentForDeclNoCache(*I); - OriginalDeclForRC = *I; + RC = getRawCommentForDeclNoCache(I); + OriginalDeclForRC = I; RawCommentAndCacheFlags Raw; if (RC) { Raw.setRaw(RC); Raw.setKind(RawCommentAndCacheFlags::FromDecl); } else Raw.setKind(RawCommentAndCacheFlags::NoCommentInDecl); - Raw.setOriginalDecl(*I); - RedeclComments[*I] = Raw; + Raw.setOriginalDecl(I); + RedeclComments[I] = Raw; if (RC) break; } @@ -371,10 +389,8 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( Raw.setKind(RawCommentAndCacheFlags::FromRedecl); Raw.setOriginalDecl(OriginalDeclForRC); - for (Decl::redecl_iterator I = D->redecls_begin(), - E = D->redecls_end(); - I != E; ++I) { - RawCommentAndCacheFlags &R = RedeclComments[*I]; + for (auto I : D->redecls()) { + RawCommentAndCacheFlags &R = RedeclComments[I]; if (R.getKind() == RawCommentAndCacheFlags::NoCommentInDecl) R = Raw; } @@ -390,10 +406,7 @@ static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod, if (!ID) return; // Add redeclared method here. - for (ObjCInterfaceDecl::known_extensions_iterator - Ext = ID->known_extensions_begin(), - ExtEnd = ID->known_extensions_end(); - Ext != ExtEnd; ++Ext) { + for (const auto *Ext : ID->known_extensions()) { if (ObjCMethodDecl *RedeclaredMethod = Ext->getMethod(ObjCMethod->getSelector(), ObjCMethod->isInstanceMethod())) @@ -409,6 +422,8 @@ comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC, ThisDeclInfo->IsFilled = false; ThisDeclInfo->fill(); ThisDeclInfo->CommentDecl = FC->getDecl(); + if (!ThisDeclInfo->TemplateParameters) + ThisDeclInfo->TemplateParameters = FC->getDeclInfo()->TemplateParameters; comments::FullComment *CFC = new (*this) comments::FullComment(FC->getBlocks(), ThisDeclInfo); @@ -418,14 +433,14 @@ 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; + return RC ? RC->parse(*this, nullptr, D) : nullptr; } comments::FullComment *ASTContext::getCommentForDecl( const Decl *D, const Preprocessor *PP) const { if (D->isInvalidDecl()) - return NULL; + return nullptr; D = adjustDeclToTemplate(D); const Decl *Canonical = D->getCanonicalDecl(); @@ -482,13 +497,12 @@ comments::FullComment *ASTContext::getCommentForDecl( } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { if (!(RD = RD->getDefinition())) - return NULL; + return nullptr; // Check non-virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = - RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { - if (I->isVirtual() || (I->getAccessSpecifier() != AS_public)) + for (const auto &I : RD->bases()) { + if (I.isVirtual() || (I.getAccessSpecifier() != AS_public)) continue; - QualType Ty = I->getType(); + QualType Ty = I.getType(); if (Ty.isNull()) continue; if (const CXXRecordDecl *NonVirtualBase = Ty->getAsCXXRecordDecl()) { @@ -500,11 +514,10 @@ comments::FullComment *ASTContext::getCommentForDecl( } } // Check virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = - RD->vbases_begin(), E = RD->vbases_end(); I != E; ++I) { - if (I->getAccessSpecifier() != AS_public) + for (const auto &I : RD->vbases()) { + if (I.getAccessSpecifier() != AS_public) continue; - QualType Ty = I->getType(); + QualType Ty = I.getType(); if (Ty.isNull()) continue; if (const CXXRecordDecl *VirtualBase = Ty->getAsCXXRecordDecl()) { @@ -515,7 +528,7 @@ comments::FullComment *ASTContext::getCommentForDecl( } } } - return NULL; + return nullptr; } // If the RawComment was attached to other redeclaration of this Decl, we @@ -576,7 +589,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( // Check if we already have a canonical template template parameter. llvm::FoldingSetNodeID ID; CanonicalTemplateTemplateParm::Profile(ID, TTP); - void *InsertPos = 0; + void *InsertPos = nullptr; CanonicalTemplateTemplateParm *Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); if (Canonical) @@ -595,7 +608,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( SourceLocation(), SourceLocation(), TTP->getDepth(), - TTP->getIndex(), 0, false, + TTP->getIndex(), nullptr, false, TTP->isParameterPack())); else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { @@ -615,7 +628,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( SourceLocation(), SourceLocation(), NTTP->getDepth(), - NTTP->getPosition(), 0, + NTTP->getPosition(), nullptr, T, TInfo, ExpandedTypes.data(), @@ -626,7 +639,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( SourceLocation(), SourceLocation(), NTTP->getDepth(), - NTTP->getPosition(), 0, + NTTP->getPosition(), nullptr, T, NTTP->isParameterPack(), TInfo); @@ -643,7 +656,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( SourceLocation(), TTP->getDepth(), TTP->getPosition(), TTP->isParameterPack(), - 0, + nullptr, TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(), CanonParams.data(), @@ -652,7 +665,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( // Get the new insert position for the node we care about. Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); - assert(Canonical == 0 && "Shouldn't be in the map!"); + assert(!Canonical && "Shouldn't be in the map!"); (void)Canonical; // Create the canonical template template parameter entry. @@ -662,13 +675,13 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( } CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { - if (!LangOpts.CPlusPlus) return 0; + if (!LangOpts.CPlusPlus) return nullptr; switch (T.getCXXABI().getKind()) { - case TargetCXXABI::GenericARM: + case TargetCXXABI::GenericARM: // Same as Itanium at this level case TargetCXXABI::iOS: - return CreateARMCXXABI(*this); - case TargetCXXABI::GenericAArch64: // Same as Itanium at this level + case TargetCXXABI::iOS64: + case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericItanium: return CreateItaniumCXXABI(*this); case TargetCXXABI::Microsoft: @@ -710,47 +723,40 @@ static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI, } ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, - const TargetInfo *t, IdentifierTable &idents, SelectorTable &sels, - Builtin::Context &builtins, - unsigned size_reserve, - bool DelayInitialization) + Builtin::Context &builtins) : FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), SubstTemplateTemplateParmPacks(this_()), - GlobalNestedNameSpecifier(0), - Int128Decl(0), UInt128Decl(0), Float128StubDecl(0), - BuiltinVaListDecl(0), - ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), ObjCProtocolClassDecl(0), - BOOLDecl(0), - CFConstantStringTypeDecl(0), ObjCInstanceTypeDecl(0), - FILEDecl(0), - jmp_bufDecl(0), sigjmp_bufDecl(0), ucontext_tDecl(0), - BlockDescriptorType(0), BlockDescriptorExtendedType(0), - cudaConfigureCallDecl(0), + GlobalNestedNameSpecifier(nullptr), + Int128Decl(nullptr), UInt128Decl(nullptr), Float128StubDecl(nullptr), + BuiltinVaListDecl(nullptr), + ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), ObjCClassDecl(nullptr), + ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr), + CFConstantStringTypeDecl(nullptr), ObjCInstanceTypeDecl(nullptr), + FILEDecl(nullptr), + jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr), ucontext_tDecl(nullptr), + BlockDescriptorType(nullptr), BlockDescriptorExtendedType(nullptr), + cudaConfigureCallDecl(nullptr), NullTypeSourceInfo(QualType()), FirstLocalImport(), LastLocalImport(), SourceMgr(SM), LangOpts(LOpts), - AddrSpaceMap(0), Target(t), PrintingPolicy(LOpts), + AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), - ExternalSource(0), Listener(0), + ExternalSource(nullptr), Listener(nullptr), Comments(SM), CommentsLoaded(false), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), - LastSDM(0, 0) + LastSDM(nullptr, 0) { - if (size_reserve > 0) Types.reserve(size_reserve); TUDecl = TranslationUnitDecl::Create(*this); - - if (!DelayInitialization) { - assert(t && "No target supplied for ASTContext initialization"); - InitBuiltinTypes(*t); - } } ASTContext::~ASTContext() { + ReleaseParentMapEntries(); + // Release the DenseMaps associated with DeclContext objects. // FIXME: Is this the ideal solution? ReleaseDeclContextMaps(); @@ -782,11 +788,19 @@ ASTContext::~ASTContext() { 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; + llvm::DeleteContainerSeconds(MangleNumberingContexts); +} + +void ASTContext::ReleaseParentMapEntries() { + if (!AllParents) return; + for (const auto &Entry : *AllParents) { + if (Entry.second.is<ast_type_traits::DynTypedNode *>()) { + delete Entry.second.get<ast_type_traits::DynTypedNode *>(); + } else { + assert(Entry.second.is<ParentVector *>()); + delete Entry.second.get<ParentVector *>(); + } + } } void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { @@ -794,8 +808,8 @@ void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { } void -ASTContext::setExternalSource(OwningPtr<ExternalASTSource> &Source) { - ExternalSource.reset(Source.take()); +ASTContext::setExternalSource(IntrusiveRefCntPtr<ExternalASTSource> Source) { + ExternalSource = Source; } void ASTContext::PrintStats() const { @@ -849,7 +863,7 @@ void ASTContext::PrintStats() const { << NumImplicitDestructors << " implicit destructors created\n"; - if (ExternalSource.get()) { + if (ExternalSource) { llvm::errs() << "\n"; ExternalSource->PrintStats(); } @@ -857,45 +871,47 @@ void ASTContext::PrintStats() const { BumpAlloc.PrintStats(); } +RecordDecl *ASTContext::buildImplicitRecord(StringRef Name, + RecordDecl::TagKind TK) const { + SourceLocation Loc; + RecordDecl *NewDecl; + if (getLangOpts().CPlusPlus) + NewDecl = CXXRecordDecl::Create(*this, TK, getTranslationUnitDecl(), Loc, + Loc, &Idents.get(Name)); + else + NewDecl = RecordDecl::Create(*this, TK, getTranslationUnitDecl(), Loc, Loc, + &Idents.get(Name)); + NewDecl->setImplicit(); + return NewDecl; +} + +TypedefDecl *ASTContext::buildImplicitTypedef(QualType T, + StringRef Name) const { + TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T); + TypedefDecl *NewDecl = TypedefDecl::Create( + const_cast<ASTContext &>(*this), getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), &Idents.get(Name), TInfo); + NewDecl->setImplicit(); + return NewDecl; +} + TypedefDecl *ASTContext::getInt128Decl() const { - if (!Int128Decl) { - TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(Int128Ty); - Int128Decl = TypedefDecl::Create(const_cast<ASTContext &>(*this), - getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - &Idents.get("__int128_t"), - TInfo); - } - + if (!Int128Decl) + Int128Decl = buildImplicitTypedef(Int128Ty, "__int128_t"); return Int128Decl; } TypedefDecl *ASTContext::getUInt128Decl() const { - if (!UInt128Decl) { - TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(UnsignedInt128Ty); - UInt128Decl = TypedefDecl::Create(const_cast<ASTContext &>(*this), - getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - &Idents.get("__uint128_t"), - TInfo); - } - + if (!UInt128Decl) + UInt128Decl = buildImplicitTypedef(UnsignedInt128Ty, "__uint128_t"); 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")); - } - + if (!Float128StubDecl) + Float128StubDecl = buildImplicitRecord("__float128"); + return Float128StubDecl; } @@ -1106,7 +1122,7 @@ FunctionDecl *ASTContext::getClassScopeSpecializationPattern( llvm::DenseMap<const FunctionDecl*, FunctionDecl *>::const_iterator Pos = ClassScopeSpecializationPattern.find(FD); if (Pos == ClassScopeSpecializationPattern.end()) - return 0; + return nullptr; return Pos->second; } @@ -1123,7 +1139,7 @@ ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos = InstantiatedFromUsingDecl.find(UUD); if (Pos == InstantiatedFromUsingDecl.end()) - return 0; + return nullptr; return Pos->second; } @@ -1143,7 +1159,7 @@ ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) { llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos = InstantiatedFromUsingShadowDecl.find(Inst); if (Pos == InstantiatedFromUsingShadowDecl.end()) - return 0; + return nullptr; return Pos->second; } @@ -1159,7 +1175,7 @@ FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) { llvm::DenseMap<FieldDecl *, FieldDecl *>::iterator Pos = InstantiatedFromUnnamedFieldDecl.find(Field); if (Pos == InstantiatedFromUnnamedFieldDecl.end()) - return 0; + return nullptr; return Pos->second; } @@ -1179,7 +1195,7 @@ ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const { llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = OverriddenMethods.find(Method->getCanonicalDecl()); if (Pos == OverriddenMethods.end()) - return 0; + return nullptr; return Pos->second.begin(); } @@ -1189,7 +1205,7 @@ ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const { llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = OverriddenMethods.find(Method->getCanonicalDecl()); if (Pos == OverriddenMethods.end()) - return 0; + return nullptr; return Pos->second.end(); } @@ -1293,13 +1309,14 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { } else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { QualType T = VD->getType(); - if (const ReferenceType* RT = T->getAs<ReferenceType>()) { + if (const ReferenceType *RT = T->getAs<ReferenceType>()) { if (ForAlignof) T = RT->getPointeeType(); else T = getPointerType(RT->getPointeeType()); } - if (!T->isIncompleteType() && !T->isFunctionType()) { + QualType BaseT = getBaseElementType(T); + if (!BaseT->isIncompleteType() && !T->isFunctionType()) { // Adjust alignments of declarations with array type by the // large-array alignment on the target. if (const ArrayType *arrayType = getAsArrayType(T)) { @@ -1311,9 +1328,6 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { MinWidth <= getTypeSize(cast<ConstantArrayType>(arrayType))) Align = std::max(Align, Target->getLargeArrayAlign()); } - - // Walk through any array types while we're at it. - T = getBaseElementType(arrayType); } Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { @@ -1618,7 +1632,7 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::MemberPointer: { const MemberPointerType *MPT = cast<MemberPointerType>(T); - llvm::tie(Width, Align) = ABI->getMemberPointerWidthAndAlign(MPT); + std::tie(Width, Align) = ABI->getMemberPointerWidthAndAlign(MPT); break; } case Type::Complex: { @@ -1632,8 +1646,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::ObjCObject: return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr()); + case Type::Adjusted: case Type::Decayed: - return getTypeInfo(cast<DecayedType>(T)->getDecayedType().getTypePtr()); + return getTypeInfo(cast<AdjustedType>(T)->getAdjustedType().getTypePtr()); case Type::ObjCInterface: { const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T); const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); @@ -1761,13 +1776,19 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { if (Target->getTriple().getArch() == llvm::Triple::xcore) return ABIAlign; // Never overalign on XCore. + const TypedefType *TT = T->getAs<TypedefType>(); + // Double and long long should be naturally aligned if possible. - if (const ComplexType* CT = T->getAs<ComplexType>()) + T = T->getBaseElementTypeUnsafe(); + if (const ComplexType *CT = T->getAs<ComplexType>()) T = CT->getElementType().getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::Double) || T->isSpecificBuiltinType(BuiltinType::LongLong) || T->isSpecificBuiltinType(BuiltinType::ULongLong)) - return std::max(ABIAlign, (unsigned)getTypeSize(T)); + // Don't increase the alignment if an alignment attribute was specified on a + // typedef declaration. + if (!TT || !TT->getDecl()->getMaxAlignment()) + return std::max(ABIAlign, (unsigned)getTypeSize(T)); return ABIAlign; } @@ -1796,9 +1817,8 @@ void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass()) DeepCollectObjCIvars(SuperClass, false, Ivars); if (!leafClass) { - for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(), - E = OI->ivar_end(); I != E; ++I) - Ivars.push_back(*I); + for (const auto *I : OI->ivars()) + Ivars.push_back(I); } else { ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI); for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv; @@ -1814,24 +1834,17 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) { // We can use protocol_iterator here instead of // all_referenced_protocol_iterator since we are walking all categories. - for (ObjCInterfaceDecl::all_protocol_iterator P = OI->all_referenced_protocol_begin(), - PE = OI->all_referenced_protocol_end(); P != PE; ++P) { - ObjCProtocolDecl *Proto = (*P); + for (auto *Proto : OI->all_referenced_protocols()) { Protocols.insert(Proto->getCanonicalDecl()); - for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), - PE = Proto->protocol_end(); P != PE; ++P) { - Protocols.insert((*P)->getCanonicalDecl()); - CollectInheritedProtocols(*P, Protocols); + for (auto *P : Proto->protocols()) { + Protocols.insert(P->getCanonicalDecl()); + CollectInheritedProtocols(P, Protocols); } } // Categories of this Interface. - for (ObjCInterfaceDecl::visible_categories_iterator - Cat = OI->visible_categories_begin(), - CatEnd = OI->visible_categories_end(); - Cat != CatEnd; ++Cat) { - CollectInheritedProtocols(*Cat, Protocols); - } + for (const auto *Cat : OI->visible_categories()) + CollectInheritedProtocols(Cat, Protocols); if (ObjCInterfaceDecl *SD = OI->getSuperClass()) while (SD) { @@ -1839,22 +1852,16 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, SD = SD->getSuperClass(); } } else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) { - for (ObjCCategoryDecl::protocol_iterator P = OC->protocol_begin(), - PE = OC->protocol_end(); P != PE; ++P) { - ObjCProtocolDecl *Proto = (*P); + for (auto *Proto : OC->protocols()) { Protocols.insert(Proto->getCanonicalDecl()); - for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), - PE = Proto->protocol_end(); P != PE; ++P) - CollectInheritedProtocols(*P, Protocols); + for (const auto *P : Proto->protocols()) + CollectInheritedProtocols(P, Protocols); } } else if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) { - for (ObjCProtocolDecl::protocol_iterator P = OP->protocol_begin(), - PE = OP->protocol_end(); P != PE; ++P) { - ObjCProtocolDecl *Proto = (*P); + for (auto *Proto : OP->protocols()) { Protocols.insert(Proto->getCanonicalDecl()); - for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), - PE = Proto->protocol_end(); P != PE; ++P) - CollectInheritedProtocols(*P, Protocols); + for (const auto *P : Proto->protocols()) + CollectInheritedProtocols(P, Protocols); } } } @@ -1862,12 +1869,8 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const { unsigned count = 0; // Count ivars declared in class extension. - for (ObjCInterfaceDecl::known_extensions_iterator - Ext = OI->known_extensions_begin(), - ExtEnd = OI->known_extensions_end(); - Ext != ExtEnd; ++Ext) { + for (const auto *Ext : OI->known_extensions()) count += Ext->ivar_size(); - } // Count ivar defined in this class's implementation. This // includes synthesized ivars. @@ -1901,7 +1904,7 @@ ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) I = ObjCImpls.find(D); if (I != ObjCImpls.end()) return cast<ObjCImplementationDecl>(I->second); - return 0; + return nullptr; } /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists. ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) { @@ -1909,7 +1912,7 @@ ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) { I = ObjCImpls.find(D); if (I != ObjCImpls.end()) return cast<ObjCCategoryImplDecl>(I->second); - return 0; + return nullptr; } /// \brief Set the implementation of ObjCInterfaceDecl. @@ -1937,7 +1940,7 @@ const ObjCInterfaceDecl *ASTContext::getObjContainingInterface( dyn_cast<ObjCImplDecl>(ND->getDeclContext())) return IMD->getClassInterface(); - return 0; + return nullptr; } /// \brief Get the copy initialization expression of VarDecl,or NULL if @@ -1948,7 +1951,7 @@ Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) { "getBlockVarCopyInits - not __block var"); llvm::DenseMap<const VarDecl*, Expr*>::iterator I = BlockVarCopyInits.find(VD); - return (I != BlockVarCopyInits.end()) ? cast<Expr>(I->second) : 0; + return (I != BlockVarCopyInits.end()) ? cast<Expr>(I->second) : nullptr; } /// \brief Set the copy inialization expression of a block var decl. @@ -1982,7 +1985,7 @@ TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T, const ASTRecordLayout & ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const { - return getObjCLayout(D, 0); + return getObjCLayout(D, nullptr); } const ASTRecordLayout & @@ -2003,7 +2006,7 @@ ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const { // Check if we've already instantiated this type. llvm::FoldingSetNodeID ID; ExtQuals::Profile(ID, baseType, quals); - void *insertPos = 0; + void *insertPos = nullptr; if (ExtQuals *eq = ExtQualNodes.FindNodeOrInsertPos(ID, insertPos)) { assert(eq->getQualifiers() == quals); return QualType(eq, fastQuals); @@ -2080,12 +2083,12 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, QualType Result; if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(T)) { - Result = getFunctionNoProtoType(FNPT->getResultType(), Info); + Result = getFunctionNoProtoType(FNPT->getReturnType(), Info); } else { const FunctionProtoType *FPT = cast<FunctionProtoType>(T); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = Info; - Result = getFunctionType(FPT->getResultType(), FPT->getArgTypes(), EPI); + Result = getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI); } return cast<FunctionType>(Result.getTypePtr()); @@ -2097,7 +2100,7 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, while (true) { const FunctionProtoType *FPT = FD->getType()->castAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - FD->setType(getFunctionType(ResultType, FPT->getArgTypes(), EPI)); + FD->setType(getFunctionType(ResultType, FPT->getParamTypes(), EPI)); if (FunctionDecl *Next = FD->getPreviousDecl()) FD = Next; else @@ -2115,7 +2118,7 @@ QualType ASTContext::getComplexType(QualType T) const { llvm::FoldingSetNodeID ID; ComplexType::Profile(ID, T); - void *InsertPos = 0; + void *InsertPos = nullptr; if (ComplexType *CT = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(CT, 0); @@ -2127,7 +2130,7 @@ QualType ASTContext::getComplexType(QualType T) const { // Get the new insert position for the node we care about. ComplexType *NewIP = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } ComplexType *New = new (*this, TypeAlignment) ComplexType(T, Canonical); Types.push_back(New); @@ -2143,7 +2146,7 @@ QualType ASTContext::getPointerType(QualType T) const { llvm::FoldingSetNodeID ID; PointerType::Profile(ID, T); - void *InsertPos = 0; + void *InsertPos = nullptr; if (PointerType *PT = PointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(PT, 0); @@ -2155,7 +2158,7 @@ QualType ASTContext::getPointerType(QualType T) const { // Get the new insert position for the node we care about. PointerType *NewIP = PointerTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } PointerType *New = new (*this, TypeAlignment) PointerType(T, Canonical); Types.push_back(New); @@ -2163,15 +2166,30 @@ QualType ASTContext::getPointerType(QualType T) const { return QualType(New, 0); } +QualType ASTContext::getAdjustedType(QualType Orig, QualType New) const { + llvm::FoldingSetNodeID ID; + AdjustedType::Profile(ID, Orig, New); + void *InsertPos = nullptr; + AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); + if (AT) + return QualType(AT, 0); + + QualType Canonical = getCanonicalType(New); + + // Get the new insert position for the node we care about. + AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!AT && "Shouldn't be in the map!"); + + AT = new (*this, TypeAlignment) + AdjustedType(Type::Adjusted, Orig, New, Canonical); + Types.push_back(AT); + AdjustedTypes.InsertNode(AT, InsertPos); + return QualType(AT, 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: @@ -2189,17 +2207,23 @@ QualType ASTContext::getDecayedType(QualType T) const { if (T->isFunctionType()) Decayed = getPointerType(T); + llvm::FoldingSetNodeID ID; + AdjustedType::Profile(ID, T, Decayed); + void *InsertPos = nullptr; + AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); + if (AT) + return QualType(AT, 0); + 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; + AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!AT && "Shouldn't be in the map!"); - DecayedType *New = - new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical); - Types.push_back(New); - DecayedTypes.InsertNode(New, InsertPos); - return QualType(New, 0); + AT = new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical); + Types.push_back(AT); + AdjustedTypes.InsertNode(AT, InsertPos); + return QualType(AT, 0); } /// getBlockPointerType - Return the uniqued reference to the type for @@ -2211,7 +2235,7 @@ QualType ASTContext::getBlockPointerType(QualType T) const { llvm::FoldingSetNodeID ID; BlockPointerType::Profile(ID, T); - void *InsertPos = 0; + void *InsertPos = nullptr; if (BlockPointerType *PT = BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(PT, 0); @@ -2225,7 +2249,7 @@ QualType ASTContext::getBlockPointerType(QualType T) const { // Get the new insert position for the node we care about. BlockPointerType *NewIP = BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } BlockPointerType *New = new (*this, TypeAlignment) BlockPointerType(T, Canonical); @@ -2246,7 +2270,7 @@ ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const { llvm::FoldingSetNodeID ID; ReferenceType::Profile(ID, T, SpelledAsLValue); - void *InsertPos = 0; + void *InsertPos = nullptr; if (LValueReferenceType *RT = LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(RT, 0); @@ -2263,7 +2287,7 @@ ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const { // Get the new insert position for the node we care about. LValueReferenceType *NewIP = LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } LValueReferenceType *New @@ -2283,7 +2307,7 @@ QualType ASTContext::getRValueReferenceType(QualType T) const { llvm::FoldingSetNodeID ID; ReferenceType::Profile(ID, T, false); - void *InsertPos = 0; + void *InsertPos = nullptr; if (RValueReferenceType *RT = RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(RT, 0); @@ -2300,7 +2324,7 @@ QualType ASTContext::getRValueReferenceType(QualType T) const { // Get the new insert position for the node we care about. RValueReferenceType *NewIP = RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } RValueReferenceType *New @@ -2318,7 +2342,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const { llvm::FoldingSetNodeID ID; MemberPointerType::Profile(ID, T, Cls); - void *InsertPos = 0; + void *InsertPos = nullptr; if (MemberPointerType *PT = MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(PT, 0); @@ -2332,7 +2356,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const { // Get the new insert position for the node we care about. MemberPointerType *NewIP = MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } MemberPointerType *New = new (*this, TypeAlignment) MemberPointerType(T, Cls, Canonical); @@ -2360,7 +2384,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, llvm::FoldingSetNodeID ID; ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals); - void *InsertPos = 0; + void *InsertPos = nullptr; if (ConstantArrayType *ATP = ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(ATP, 0); @@ -2377,7 +2401,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, // Get the new insert position for the node we care about. ConstantArrayType *NewIP = ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } ConstantArrayType *New = new(*this,TypeAlignment) @@ -2495,7 +2519,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { const IncompleteArrayType *iat = cast<IncompleteArrayType>(ty); result = getVariableArrayType( getVariableArrayDecayedType(iat->getElementType()), - /*size*/ 0, + /*size*/ nullptr, ArrayType::Normal, iat->getIndexTypeCVRQualifiers(), SourceRange()); @@ -2507,7 +2531,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { const VariableArrayType *vat = cast<VariableArrayType>(ty); result = getVariableArrayType( getVariableArrayDecayedType(vat->getElementType()), - /*size*/ 0, + /*size*/ nullptr, ArrayType::Star, vat->getIndexTypeCVRQualifiers(), vat->getBracketsRange()); @@ -2577,7 +2601,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, SplitQualType canonElementType = getCanonicalType(elementType).split(); - void *insertPos = 0; + void *insertPos = nullptr; llvm::FoldingSetNodeID ID; DependentSizedArrayType::Profile(ID, *this, QualType(canonElementType.Ty, 0), @@ -2622,7 +2646,7 @@ QualType ASTContext::getIncompleteArrayType(QualType elementType, llvm::FoldingSetNodeID ID; IncompleteArrayType::Profile(ID, elementType, ASM, elementTypeQuals); - void *insertPos = 0; + void *insertPos = nullptr; if (IncompleteArrayType *iat = IncompleteArrayTypes.FindNodeOrInsertPos(ID, insertPos)) return QualType(iat, 0); @@ -2662,7 +2686,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, llvm::FoldingSetNodeID ID; VectorType::Profile(ID, vecType, NumElts, Type::Vector, VecKind); - void *InsertPos = 0; + void *InsertPos = nullptr; if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(VTP, 0); @@ -2674,7 +2698,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, // Get the new insert position for the node we care about. VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } VectorType *New = new (*this, TypeAlignment) VectorType(vecType, NumElts, Canonical, VecKind); @@ -2693,7 +2717,7 @@ ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) const { llvm::FoldingSetNodeID ID; VectorType::Profile(ID, vecType, NumElts, Type::ExtVector, VectorType::GenericVector); - void *InsertPos = 0; + void *InsertPos = nullptr; if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(VTP, 0); @@ -2705,7 +2729,7 @@ ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) const { // Get the new insert position for the node we care about. VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } ExtVectorType *New = new (*this, TypeAlignment) ExtVectorType(vecType, NumElts, Canonical); @@ -2722,7 +2746,7 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType, DependentSizedExtVectorType::Profile(ID, *this, getCanonicalType(vecType), SizeExpr); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentSizedExtVectorType *Canon = DependentSizedExtVectorTypes.FindNodeOrInsertPos(ID, InsertPos); DependentSizedExtVectorType *New; @@ -2768,7 +2792,7 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, llvm::FoldingSetNodeID ID; FunctionNoProtoType::Profile(ID, ResultTy, Info); - void *InsertPos = 0; + void *InsertPos = nullptr; if (FunctionNoProtoType *FT = FunctionNoProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(FT, 0); @@ -2780,7 +2804,7 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, // Get the new insert position for the node we care about. FunctionNoProtoType *NewIP = FunctionNoProtoTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } FunctionProtoType::ExtInfo newInfo = Info.withCallingConv(CallConv); @@ -2798,8 +2822,6 @@ static bool isCanonicalResultType(QualType T) { T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone); } -/// getFunctionType - Return a normal function type with a typed argument -/// list. isVariadic indicates whether the argument list includes '...'. QualType ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, const FunctionProtoType::ExtProtoInfo &EPI) const { @@ -2811,7 +2833,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI, *this); - void *InsertPos = 0; + void *InsertPos = nullptr; if (FunctionProtoType *FTP = FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(FTP, 0); @@ -2851,7 +2873,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, // Get the new insert position for the node we care about. FunctionProtoType *NewIP = FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } // FunctionProtoType objects are allocated with extra bytes after @@ -2873,7 +2895,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, } else if (EPI.ExceptionSpecType == EST_Unevaluated) { Size += sizeof(FunctionDecl*); } - if (EPI.ConsumedArguments) + if (EPI.ConsumedParameters) Size += NumArgs * sizeof(bool); FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); @@ -2995,7 +3017,7 @@ QualType ASTContext::getAttributedType(AttributedType::Kind attrKind, llvm::FoldingSetNodeID id; AttributedType::Profile(id, attrKind, modifiedType, equivalentType); - void *insertPos = 0; + void *insertPos = nullptr; AttributedType *type = AttributedTypes.FindNodeOrInsertPos(id, insertPos); if (type) return QualType(type, 0); @@ -3019,7 +3041,7 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, llvm::FoldingSetNodeID ID; SubstTemplateTypeParmType::Profile(ID, Parm, Replacement); - void *InsertPos = 0; + void *InsertPos = nullptr; SubstTemplateTypeParmType *SubstParm = SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -3038,17 +3060,15 @@ QualType ASTContext::getSubstTemplateTypeParmPackType( const TemplateTypeParmType *Parm, const TemplateArgument &ArgPack) { #ifndef NDEBUG - for (TemplateArgument::pack_iterator P = ArgPack.pack_begin(), - PEnd = ArgPack.pack_end(); - P != PEnd; ++P) { - assert(P->getKind() == TemplateArgument::Type &&"Pack contains a non-type"); - assert(P->getAsType().isCanonical() && "Pack contains non-canonical type"); + for (const auto &P : ArgPack.pack_elements()) { + assert(P.getKind() == TemplateArgument::Type &&"Pack contains a non-type"); + assert(P.getAsType().isCanonical() && "Pack contains non-canonical type"); } #endif llvm::FoldingSetNodeID ID; SubstTemplateTypeParmPackType::Profile(ID, Parm, ArgPack); - void *InsertPos = 0; + void *InsertPos = nullptr; if (SubstTemplateTypeParmPackType *SubstParm = SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(SubstParm, 0); @@ -3077,7 +3097,7 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, TemplateTypeParmDecl *TTPDecl) const { llvm::FoldingSetNodeID ID; TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, TTPDecl); - void *InsertPos = 0; + void *InsertPos = nullptr; TemplateTypeParmType *TypeParm = TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -3218,7 +3238,7 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, TemplateSpecializationType::Profile(ID, CanonTemplate, CanonArgs.data(), NumArgs, *this); - void *InsertPos = 0; + void *InsertPos = nullptr; TemplateSpecializationType *Spec = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -3246,7 +3266,7 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, llvm::FoldingSetNodeID ID; ElaboratedType::Profile(ID, Keyword, NNS, NamedType); - void *InsertPos = 0; + void *InsertPos = nullptr; ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) return QualType(T, 0); @@ -3270,7 +3290,7 @@ ASTContext::getParenType(QualType InnerType) const { llvm::FoldingSetNodeID ID; ParenType::Profile(ID, InnerType); - void *InsertPos = 0; + void *InsertPos = nullptr; ParenType *T = ParenTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) return QualType(T, 0); @@ -3293,8 +3313,6 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType Canon) const { - assert(NNS->isDependent() && "nested-name-specifier must be dependent"); - if (Canon.isNull()) { NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); ElaboratedTypeKeyword CanonKeyword = Keyword; @@ -3308,7 +3326,7 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, llvm::FoldingSetNodeID ID; DependentNameType::Profile(ID, Keyword, NNS, Name); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentNameType *T = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) @@ -3349,7 +3367,7 @@ ASTContext::getDependentTemplateSpecializationType( DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS, Name, NumArgs, Args); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentTemplateSpecializationType *T = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) @@ -3395,7 +3413,7 @@ QualType ASTContext::getPackExpansionType(QualType Pattern, assert(Pattern->containsUnexpandedParameterPack() && "Pack expansions must expand one or more parameter packs"); - void *InsertPos = 0; + void *InsertPos = nullptr; PackExpansionType *T = PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) @@ -3408,7 +3426,7 @@ QualType ASTContext::getPackExpansionType(QualType Pattern, // contains an alias template specialization which ignores one of its // parameters. if (Canon->containsUnexpandedParameterPack()) { - Canon = getPackExpansionType(getCanonicalType(Pattern), NumExpansions); + Canon = getPackExpansionType(Canon, NumExpansions); // Find the insert position again, in case we inserted an element into // PackExpansionTypes and invalidated our insert position. @@ -3419,7 +3437,7 @@ QualType ASTContext::getPackExpansionType(QualType Pattern, T = new (*this) PackExpansionType(Pattern, Canon, NumExpansions); Types.push_back(T); PackExpansionTypes.InsertNode(T, InsertPos); - return QualType(T, 0); + return QualType(T, 0); } /// CmpProtocolNames - Comparison predicate for sorting protocols @@ -3470,7 +3488,7 @@ QualType ASTContext::getObjCObjectType(QualType BaseType, // Look in the folding set for an existing type. llvm::FoldingSetNodeID ID; ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols); - void *InsertPos = 0; + void *InsertPos = nullptr; if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(QT, 0); @@ -3507,13 +3525,79 @@ QualType ASTContext::getObjCObjectType(QualType BaseType, return QualType(T, 0); } +/// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's +/// protocol list adopt all protocols in QT's qualified-id protocol +/// list. +bool ASTContext::ObjCObjectAdoptsQTypeProtocols(QualType QT, + ObjCInterfaceDecl *IC) { + if (!QT->isObjCQualifiedIdType()) + return false; + + if (const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>()) { + // If both the right and left sides have qualifiers. + for (auto *Proto : OPT->quals()) { + if (!IC->ClassImplementsProtocol(Proto, false)) + return false; + } + return true; + } + return false; +} + +/// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in +/// QT's qualified-id protocol list adopt all protocols in IDecl's list +/// of protocols. +bool ASTContext::QIdProtocolsAdoptObjCObjectProtocols(QualType QT, + ObjCInterfaceDecl *IDecl) { + if (!QT->isObjCQualifiedIdType()) + return false; + const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>(); + if (!OPT) + return false; + if (!IDecl->hasDefinition()) + return false; + llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocols; + CollectInheritedProtocols(IDecl, InheritedProtocols); + if (InheritedProtocols.empty()) + return false; + // Check that if every protocol in list of id<plist> conforms to a protcol + // of IDecl's, then bridge casting is ok. + bool Conforms = false; + for (auto *Proto : OPT->quals()) { + Conforms = false; + for (auto *PI : InheritedProtocols) { + if (ProtocolCompatibleWithProtocol(Proto, PI)) { + Conforms = true; + break; + } + } + if (!Conforms) + break; + } + if (Conforms) + return true; + + for (auto *PI : InheritedProtocols) { + // If both the right and left sides have qualifiers. + bool Adopts = false; + for (auto *Proto : OPT->quals()) { + // return 'true' if 'PI' is in the inheritance hierarchy of Proto + if ((Adopts = ProtocolCompatibleWithProtocol(PI, Proto))) + break; + } + if (!Adopts) + return false; + } + return true; +} + /// getObjCObjectPointerType - Return a ObjCObjectPointerType type for /// the given object type. QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const { llvm::FoldingSetNodeID ID; ObjCObjectPointerType::Profile(ID, ObjectT); - void *InsertPos = 0; + void *InsertPos = nullptr; if (ObjCObjectPointerType *QT = ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(QT, 0); @@ -3572,7 +3656,7 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const { llvm::FoldingSetNodeID ID; DependentTypeOfExprType::Profile(ID, *this, tofExpr); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentTypeOfExprType *Canon = DependentTypeOfExprTypes.FindNodeOrInsertPos(ID, InsertPos); if (Canon) { @@ -3596,10 +3680,10 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const { } /// getTypeOfType - Unlike many "get<Type>" functions, we don't unique -/// TypeOfType AST's. The only motivation to unique these nodes would be +/// TypeOfType nodes. The only motivation to unique these nodes would be /// memory savings. Since typeof(t) is fairly uncommon, space shouldn't be -/// an issue. This doesn't effect the type checker, since it operates -/// on canonical type's (which are always unique). +/// an issue. This doesn't affect the type checker, since it operates +/// on canonical types (which are always unique). QualType ASTContext::getTypeOfType(QualType tofType) const { QualType Canonical = getCanonicalType(tofType); TypeOfType *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical); @@ -3608,39 +3692,34 @@ QualType ASTContext::getTypeOfType(QualType tofType) const { } -/// getDecltypeType - Unlike many "get<Type>" functions, we don't unique -/// DecltypeType AST's. The only motivation to unique these nodes would be -/// memory savings. Since decltype(t) is fairly uncommon, space shouldn't be -/// an issue. This doesn't effect the type checker, since it operates -/// on canonical types (which are always unique). +/// \brief Unlike many "get<Type>" functions, we don't unique DecltypeType +/// nodes. This would never be helpful, since each such type has its own +/// expression, and would not give a significant memory saving, since there +/// is an Expr tree under each such type. QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const { DecltypeType *dt; - - // C++0x [temp.type]p2: + + // C++11 [temp.type]p2: // If an expression e involves a template parameter, decltype(e) denotes a - // unique dependent type. Two such decltype-specifiers refer to the same - // type only if their expressions are equivalent (14.5.6.1). + // unique dependent type. Two such decltype-specifiers refer to the same + // type only if their expressions are equivalent (14.5.6.1). if (e->isInstantiationDependent()) { llvm::FoldingSetNodeID ID; DependentDecltypeType::Profile(ID, *this, e); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentDecltypeType *Canon = DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos); - if (Canon) { - // We already have a "canonical" version of an equivalent, dependent - // decltype type. Use that as our canonical type. - dt = new (*this, TypeAlignment) DecltypeType(e, UnderlyingType, - QualType((DecltypeType*)Canon, 0)); - } else { + if (!Canon) { // Build a new, canonical typeof(expr) type. Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e); DependentDecltypeTypes.InsertNode(Canon, InsertPos); - dt = Canon; } + dt = new (*this, TypeAlignment) + DecltypeType(e, UnderlyingType, QualType((DecltypeType *)Canon, 0)); } else { - dt = new (*this, TypeAlignment) DecltypeType(e, UnderlyingType, - getCanonicalType(UnderlyingType)); + dt = new (*this, TypeAlignment) + DecltypeType(e, UnderlyingType, getCanonicalType(UnderlyingType)); } Types.push_back(dt); return QualType(dt, 0); @@ -3670,7 +3749,7 @@ QualType ASTContext::getAutoType(QualType DeducedType, bool IsDecltypeAuto, return getAutoDeductType(); // Look in the folding set for an existing type. - void *InsertPos = 0; + void *InsertPos = nullptr; llvm::FoldingSetNodeID ID; AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent); if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos)) @@ -3693,7 +3772,7 @@ QualType ASTContext::getAtomicType(QualType T) const { llvm::FoldingSetNodeID ID; AtomicType::Profile(ID, T); - void *InsertPos = 0; + void *InsertPos = nullptr; if (AtomicType *AT = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(AT, 0); @@ -3705,7 +3784,7 @@ QualType ASTContext::getAtomicType(QualType T) const { // Get the new insert position for the node we care about. AtomicType *NewIP = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } AtomicType *New = new (*this, TypeAlignment) AtomicType(T, Canonical); Types.push_back(New); @@ -4064,7 +4143,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { NestedNameSpecifier * ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { if (!NNS) - return 0; + return nullptr; switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: @@ -4076,13 +4155,13 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { case NestedNameSpecifier::Namespace: // A namespace is canonical; build a nested-name-specifier with // this namespace and no prefix. - return NestedNameSpecifier::Create(*this, 0, + return NestedNameSpecifier::Create(*this, nullptr, NNS->getAsNamespace()->getOriginalNamespace()); case NestedNameSpecifier::NamespaceAlias: // A namespace is canonical; build a nested-name-specifier with // this namespace and no prefix. - return NestedNameSpecifier::Create(*this, 0, + return NestedNameSpecifier::Create(*this, nullptr, NNS->getAsNamespaceAlias()->getNamespace() ->getOriginalNamespace()); @@ -4104,8 +4183,8 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { // Otherwise, just canonicalize the type, and force it to be a TypeSpec. // FIXME: Why are TypeSpec and TypeSpecWithTemplate distinct in the // first place? - return NestedNameSpecifier::Create(*this, 0, false, - const_cast<Type*>(T.getTypePtr())); + return NestedNameSpecifier::Create(*this, nullptr, false, + const_cast<Type *>(T.getTypePtr())); } case NestedNameSpecifier::Global: @@ -4127,7 +4206,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { // Handle the common negative case fast. if (!isa<ArrayType>(T.getCanonicalType())) - return 0; + return nullptr; // Apply any qualifiers from the array type to the element type. This // implements C99 6.7.3p8: "If the specification of an array type includes @@ -4142,7 +4221,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { // If we have a simple case, just return now. const ArrayType *ATy = dyn_cast<ArrayType>(split.Ty); - if (ATy == 0 || qs.empty()) + if (!ATy || qs.empty()) return ATy; // Otherwise, we have an array and we have qualifiers on it. Push the @@ -4428,7 +4507,7 @@ static const Type *getIntegerTypeForEnum(const EnumType *ET) { // FIXME: In C++, enum types are never integer types. if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped()) return ET->getDecl()->getIntegerType().getTypePtr(); - return NULL; + return nullptr; } /// getIntegerTypeOrder - Returns the highest ranked integer type: @@ -4479,22 +4558,10 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const { return 1; } -static RecordDecl * -CreateRecordDecl(const ASTContext &Ctx, RecordDecl::TagKind TK, - DeclContext *DC, IdentifierInfo *Id) { - SourceLocation Loc; - if (Ctx.getLangOpts().CPlusPlus) - return CXXRecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id); - else - return RecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id); -} - // getCFConstantStringType - Return the type used for constant CFStrings. QualType ASTContext::getCFConstantStringType() const { if (!CFConstantStringTypeDecl) { - CFConstantStringTypeDecl = - CreateRecordDecl(*this, TTK_Struct, TUDecl, - &Idents.get("NSConstantString")); + CFConstantStringTypeDecl = buildImplicitRecord("NSConstantString"); CFConstantStringTypeDecl->startDefinition(); QualType FieldTypes[4]; @@ -4512,9 +4579,9 @@ QualType ASTContext::getCFConstantStringType() const { for (unsigned i = 0; i < 4; ++i) { FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl, SourceLocation(), - SourceLocation(), 0, - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, + SourceLocation(), nullptr, + FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -4529,8 +4596,7 @@ QualType ASTContext::getCFConstantStringType() const { QualType ASTContext::getObjCSuperType() const { if (ObjCSuperType.isNull()) { - RecordDecl *ObjCSuperTypeDecl = - CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("objc_super")); + RecordDecl *ObjCSuperTypeDecl = buildImplicitRecord("objc_super"); TUDecl->addDecl(ObjCSuperTypeDecl); ObjCSuperType = getTagDeclType(ObjCSuperTypeDecl); } @@ -4547,12 +4613,11 @@ QualType ASTContext::getBlockDescriptorType() const { if (BlockDescriptorType) return getTagDeclType(BlockDescriptorType); - RecordDecl *T; + RecordDecl *RD; // FIXME: Needs the FlagAppleBlock bit. - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, - &Idents.get("__block_descriptor")); - T->startDefinition(); - + RD = buildImplicitRecord("__block_descriptor"); + RD->startDefinition(); + QualType FieldTypes[] = { UnsignedLongTy, UnsignedLongTy, @@ -4564,20 +4629,17 @@ QualType ASTContext::getBlockDescriptorType() const { }; for (size_t i = 0; i < 2; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - SourceLocation(), - &Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, - /*Mutable=*/false, - ICIS_NoInit); + FieldDecl *Field = FieldDecl::Create( + *this, RD, SourceLocation(), SourceLocation(), + &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); - T->addDecl(Field); + RD->addDecl(Field); } - T->completeDefinition(); + RD->completeDefinition(); - BlockDescriptorType = T; + BlockDescriptorType = RD; return getTagDeclType(BlockDescriptorType); } @@ -4586,12 +4648,11 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { if (BlockDescriptorExtendedType) return getTagDeclType(BlockDescriptorExtendedType); - RecordDecl *T; + RecordDecl *RD; // FIXME: Needs the FlagAppleBlock bit. - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, - &Idents.get("__block_descriptor_withcopydispose")); - T->startDefinition(); - + RD = buildImplicitRecord("__block_descriptor_withcopydispose"); + RD->startDefinition(); + QualType FieldTypes[] = { UnsignedLongTy, UnsignedLongTy, @@ -4607,21 +4668,18 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { }; for (size_t i = 0; i < 4; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - SourceLocation(), - &Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, - /*Mutable=*/false, - ICIS_NoInit); + FieldDecl *Field = FieldDecl::Create( + *this, RD, SourceLocation(), SourceLocation(), + &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, + /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); - T->addDecl(Field); + RD->addDecl(Field); } - T->completeDefinition(); - - BlockDescriptorExtendedType = T; + RD->completeDefinition(); + BlockDescriptorExtendedType = RD; return getTagDeclType(BlockDescriptorExtendedType); } @@ -4691,12 +4749,8 @@ bool ASTContext::getByrefLifetime(QualType Ty, TypedefDecl *ASTContext::getObjCInstanceTypeDecl() { if (!ObjCInstanceTypeDecl) - ObjCInstanceTypeDecl = TypedefDecl::Create(*this, - getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - &Idents.get("instancetype"), - getTrivialTypeSourceInfo(getObjCIdType())); + ObjCInstanceTypeDecl = + buildImplicitTypedef(getObjCIdType(), "instancetype"); return ObjCInstanceTypeDecl; } @@ -4727,6 +4781,12 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const { return sz; } +bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const { + return getLangOpts().MSVCCompat && VD->isStaticDataMember() && + VD->getType()->isIntegralOrEnumerationType() && + !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit(); +} + static inline std::string charUnitsToString(const CharUnits &CU) { return llvm::itostr(CU.getQuantity()); @@ -4742,21 +4802,19 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { Expr->getType()->getAs<BlockPointerType>()->getPointeeType(); // Encode result type. if (getLangOpts().EncodeExtendedBlockSig) - getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, - BlockTy->getAs<FunctionType>()->getResultType(), - S, true /*Extended*/); + getObjCEncodingForMethodParameter( + Decl::OBJC_TQ_None, BlockTy->getAs<FunctionType>()->getReturnType(), S, + true /*Extended*/); else - getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(), - S); + getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getReturnType(), S); // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! SourceLocation Loc; CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy); CharUnits ParmOffset = PtrSize; - for (BlockDecl::param_const_iterator PI = Decl->param_begin(), - E = Decl->param_end(); PI != E; ++PI) { - QualType PType = (*PI)->getType(); + for (auto PI : Decl->params()) { + QualType PType = PI->getType(); CharUnits sz = getObjCEncodingTypeSize(PType); if (sz.isZero()) continue; @@ -4770,9 +4828,7 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { // Argument types. ParmOffset = PtrSize; - for (BlockDecl::param_const_iterator PI = Decl->param_begin(), E = - Decl->param_end(); PI != E; ++PI) { - ParmVarDecl *PVDecl = *PI; + for (auto PVDecl : Decl->params()) { QualType PType = PVDecl->getOriginalType(); if (const ArrayType *AT = dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { @@ -4797,12 +4853,11 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S) { // Encode result type. - getObjCEncodingForType(Decl->getResultType(), S); + getObjCEncodingForType(Decl->getReturnType(), S); CharUnits ParmOffset; // Compute size of all parameters. - for (FunctionDecl::param_const_iterator PI = Decl->param_begin(), - E = Decl->param_end(); PI != E; ++PI) { - QualType PType = (*PI)->getType(); + for (auto PI : Decl->params()) { + QualType PType = PI->getType(); CharUnits sz = getObjCEncodingTypeSize(PType); if (sz.isZero()) continue; @@ -4815,9 +4870,7 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, ParmOffset = CharUnits::Zero(); // Argument types. - for (FunctionDecl::param_const_iterator PI = Decl->param_begin(), - E = Decl->param_end(); PI != E; ++PI) { - ParmVarDecl *PVDecl = *PI; + for (auto PVDecl : Decl->params()) { QualType PType = PVDecl->getOriginalType(); if (const ArrayType *AT = dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { @@ -4844,7 +4897,7 @@ void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, // Encode type qualifer, 'in', 'inout', etc. for the parameter. getObjCEncodingForTypeQualifier(QT, S); // Encode parameter type. - getObjCEncodingForTypeImpl(T, S, true, true, 0, + getObjCEncodingForTypeImpl(T, S, true, true, nullptr, true /*OutermostType*/, false /*EncodingProperty*/, false /*StructField*/, @@ -4859,8 +4912,8 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, bool Extended) const { // FIXME: This is not very efficient. // Encode return type. - getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(), - Decl->getResultType(), S, Extended); + getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(), + Decl->getReturnType(), S, Extended); // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! @@ -4907,6 +4960,26 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, return false; } +ObjCPropertyImplDecl * +ASTContext::getObjCPropertyImplDeclForPropertyDecl( + const ObjCPropertyDecl *PD, + const Decl *Container) const { + if (!Container) + return nullptr; + if (const ObjCCategoryImplDecl *CID = + dyn_cast<ObjCCategoryImplDecl>(Container)) { + for (auto *PID : CID->property_impls()) + if (PID->getPropertyDecl() == PD) + return PID; + } else { + const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container); + for (auto *PID : OID->property_impls()) + if (PID->getPropertyDecl() == PD) + return PID; + } + return nullptr; +} + /// getObjCEncodingForPropertyDecl - Return the encoded type for this /// property declaration. If non-NULL, Container must be either an /// ObjCCategoryImplDecl or ObjCImplementationDecl; it should only be @@ -4937,39 +5010,14 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, std::string& S) const { // Collect information from the property implementation decl(s). bool Dynamic = false; - ObjCPropertyImplDecl *SynthesizePID = 0; - - // FIXME: Duplicated code due to poor abstraction. - if (Container) { - if (const ObjCCategoryImplDecl *CID = - dyn_cast<ObjCCategoryImplDecl>(Container)) { - for (ObjCCategoryImplDecl::propimpl_iterator - i = CID->propimpl_begin(), e = CID->propimpl_end(); - i != e; ++i) { - ObjCPropertyImplDecl *PID = *i; - if (PID->getPropertyDecl() == PD) { - if (PID->getPropertyImplementation()==ObjCPropertyImplDecl::Dynamic) { - Dynamic = true; - } else { - SynthesizePID = PID; - } - } - } - } else { - const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container); - for (ObjCCategoryImplDecl::propimpl_iterator - i = OID->propimpl_begin(), e = OID->propimpl_end(); - i != e; ++i) { - ObjCPropertyImplDecl *PID = *i; - if (PID->getPropertyDecl() == PD) { - if (PID->getPropertyImplementation()==ObjCPropertyImplDecl::Dynamic) { - Dynamic = true; - } else { - SynthesizePID = PID; - } - } - } - } + ObjCPropertyImplDecl *SynthesizePID = nullptr; + + if (ObjCPropertyImplDecl *PropertyImpDecl = + getObjCPropertyImplDeclForPropertyDecl(PD, Container)) { + if (PropertyImpDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + Dynamic = true; + else + SynthesizePID = PropertyImpDecl; } // FIXME: This is not very efficient. @@ -4978,9 +5026,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, // Encode result type. // GCC has some special rules regarding encoding of properties which // closely resembles encoding of ivars. - getObjCEncodingForTypeImpl(PD->getType(), S, true, true, 0, - true /* outermost type */, - true /* encoding for property */); + getObjCEncodingForPropertyType(PD->getType(), S); if (PD->isReadOnly()) { S += ",R"; @@ -4988,6 +5034,8 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, S += ",C"; if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) S += ",&"; + if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) + S += ",W"; } else { switch (PD->getSetterKind()) { case ObjCPropertyDecl::Assign: break; @@ -5051,6 +5099,16 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S, true /* outermost type */); } +void ASTContext::getObjCEncodingForPropertyType(QualType T, + std::string& S) const { + // Encode result type. + // GCC has some special rules regarding encoding of properties which + // closely resembles encoding of ivars. + getObjCEncodingForTypeImpl(T, S, true, true, nullptr, + true /* outermost type */, + true /* encoding property */); +} + static char getObjCEncodingForPrimitiveKind(const ASTContext *C, BuiltinType::Kind kind) { switch (kind) { @@ -5180,15 +5238,15 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::Complex: { const ComplexType *CT = T->castAs<ComplexType>(); S += 'j'; - getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, 0, false, - false); + getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr, + false, false); return; } case Type::Atomic: { const AtomicType *AT = T->castAs<AtomicType>(); S += 'A'; - getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, 0, + getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr, false, false); return; } @@ -5260,7 +5318,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, getLegacyIntegralTypeEncoding(PointeeTy); getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures, - NULL); + nullptr); return; } @@ -5322,9 +5380,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (!RDecl->isUnion()) { getObjCEncodingForStructureImpl(RDecl, S, FD); } else { - for (RecordDecl::field_iterator Field = RDecl->field_begin(), - FieldEnd = RDecl->field_end(); - Field != FieldEnd; ++Field) { + for (const auto *Field : RDecl->fields()) { if (FD) { S += '"'; S += Field->getNameAsString(); @@ -5334,7 +5390,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Special case bit-fields. if (Field->isBitField()) { getObjCEncodingForTypeImpl(Field->getType(), S, false, true, - *Field); + Field); } else { QualType qt = Field->getType(); getLegacyIntegralTypeEncoding(qt); @@ -5358,37 +5414,38 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += '<'; // Block return type - getObjCEncodingForTypeImpl(FT->getResultType(), S, - ExpandPointedToStructures, ExpandStructures, - FD, - false /* OutermostType */, - EncodingProperty, - false /* StructField */, - EncodeBlockParameters, - EncodeClassNames); + getObjCEncodingForTypeImpl( + FT->getReturnType(), S, ExpandPointedToStructures, ExpandStructures, + FD, false /* OutermostType */, EncodingProperty, + false /* StructField */, EncodeBlockParameters, EncodeClassNames); // Block self S += "@?"; // Block parameters if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) { - for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(), - E = FPT->arg_type_end(); I && (I != E); ++I) { - getObjCEncodingForTypeImpl(*I, S, - ExpandPointedToStructures, - ExpandStructures, - FD, - false /* OutermostType */, - EncodingProperty, - false /* StructField */, - EncodeBlockParameters, - EncodeClassNames); - } + for (const auto &I : FPT->param_types()) + getObjCEncodingForTypeImpl( + I, S, ExpandPointedToStructures, ExpandStructures, FD, + false /* OutermostType */, EncodingProperty, + false /* StructField */, EncodeBlockParameters, EncodeClassNames); } S += '>'; } return; } - case Type::ObjCObject: + case Type::ObjCObject: { + // hack to match legacy encoding of *id and *Class + QualType Ty = getObjCObjectPointerType(CT); + if (Ty->isObjCIdType()) { + S += "{objc_object=}"; + return; + } + else if (Ty->isObjCClassType()) { + S += "{objc_class=}"; + return; + } + } + case Type::ObjCInterface: { // Ignore protocol qualifiers when mangling at this level. T = T->castAs<ObjCObjectType>()->getBaseType(); @@ -5440,10 +5497,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Note that we do extended encoding of protocol qualifer list // Only when doing ivar or property encoding. S += '"'; - for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), - E = OPT->qual_end(); I != E; ++I) { + for (const auto *I : OPT->quals()) { S += '<'; - S += (*I)->getNameAsString(); + S += I->getNameAsString(); S += '>'; } S += '"'; @@ -5475,7 +5531,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures, - NULL, + nullptr, false, false, false, false, false, /*EncodePointerToObjCTypedef*/true); return; @@ -5486,10 +5542,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, (FD || EncodingProperty || EncodeClassNames)) { S += '"'; S += OPT->getInterfaceDecl()->getIdentifier()->getName(); - for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), - E = OPT->qual_end(); I != E; ++I) { + for (const auto *I : OPT->quals()) { S += '<'; - S += (*I)->getNameAsString(); + S += I->getNameAsString(); S += '>'; } S += '"'; @@ -5542,11 +5597,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, const ASTRecordLayout &layout = getASTRecordLayout(RDecl); if (CXXRec) { - for (CXXRecordDecl::base_class_iterator - BI = CXXRec->bases_begin(), - BE = CXXRec->bases_end(); BI != BE; ++BI) { - if (!BI->isVirtual()) { - CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl(); + for (const auto &BI : CXXRec->bases()) { + if (!BI.isVirtual()) { + CXXRecordDecl *base = BI.getType()->getAsCXXRecordDecl(); if (base->isEmpty()) continue; uint64_t offs = toBits(layout.getBaseClassOffset(base)); @@ -5566,10 +5619,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, } if (CXXRec && includeVBases) { - for (CXXRecordDecl::base_class_iterator - BI = CXXRec->vbases_begin(), - BE = CXXRec->vbases_end(); BI != BE; ++BI) { - CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl(); + for (const auto &BI : CXXRec->vbases()) { + CXXRecordDecl *base = BI.getType()->getAsCXXRecordDecl(); if (base->isEmpty()) continue; uint64_t offs = toBits(layout.getVBaseClassOffset(base)); @@ -5587,7 +5638,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, size = layout.getSize(); } +#ifndef NDEBUG uint64_t CurOffs = 0; +#endif std::multimap<uint64_t, NamedDecl *>::iterator CurLayObj = FieldOrBaseOffsets.begin(); @@ -5601,19 +5654,21 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, S += '"'; } S += "^^?"; +#ifndef NDEBUG CurOffs += getTypeSize(VoidPtrTy); +#endif } if (!RDecl->hasFlexibleArrayMember()) { // Mark the end of the structure. uint64_t offs = toBits(size); FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), - std::make_pair(offs, (NamedDecl*)0)); + std::make_pair(offs, nullptr)); } for (; CurLayObj != FieldOrBaseOffsets.end(); ++CurLayObj) { +#ifndef NDEBUG assert(CurOffs <= CurLayObj->first); - if (CurOffs < CurLayObj->first) { uint64_t padding = CurLayObj->first - CurOffs; // FIXME: There doesn't seem to be a way to indicate in the encoding that @@ -5625,9 +5680,10 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, // longer then though. CurOffs += padding; } +#endif NamedDecl *dcl = CurLayObj->second; - if (dcl == 0) + if (!dcl) break; // reached end of structure. if (CXXRecordDecl *base = dyn_cast<CXXRecordDecl>(dcl)) { @@ -5637,7 +5693,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, // making the encoding type bigger than it really is. getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false); assert(!base->isEmpty()); +#ifndef NDEBUG CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize()); +#endif } else { FieldDecl *field = cast<FieldDecl>(dcl); if (FD) { @@ -5648,7 +5706,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (field->isBitField()) { EncodeBitField(this, S, field->getType(), field); +#ifndef NDEBUG CurOffs += field->getBitWidthValue(*this); +#endif } else { QualType qt = field->getType(); getLegacyIntegralTypeEncoding(qt); @@ -5656,7 +5716,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, /*OutermostType*/false, /*EncodingProperty*/false, /*StructField*/true); +#ifndef NDEBUG CurOffs += getTypeSize(field->getType()); +#endif } } } @@ -5680,41 +5742,27 @@ void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, TypedefDecl *ASTContext::getObjCIdDecl() const { if (!ObjCIdDecl) { - QualType T = getObjCObjectType(ObjCBuiltinIdTy, 0, 0); + QualType T = getObjCObjectType(ObjCBuiltinIdTy, nullptr, 0); T = getObjCObjectPointerType(T); - TypeSourceInfo *IdInfo = getTrivialTypeSourceInfo(T); - ObjCIdDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this), - getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Idents.get("id"), IdInfo); + ObjCIdDecl = buildImplicitTypedef(T, "id"); } - return ObjCIdDecl; } TypedefDecl *ASTContext::getObjCSelDecl() const { if (!ObjCSelDecl) { - QualType SelT = getPointerType(ObjCBuiltinSelTy); - TypeSourceInfo *SelInfo = getTrivialTypeSourceInfo(SelT); - ObjCSelDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this), - getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Idents.get("SEL"), SelInfo); + QualType T = getPointerType(ObjCBuiltinSelTy); + ObjCSelDecl = buildImplicitTypedef(T, "SEL"); } return ObjCSelDecl; } TypedefDecl *ASTContext::getObjCClassDecl() const { if (!ObjCClassDecl) { - QualType T = getObjCObjectType(ObjCBuiltinClassTy, 0, 0); + QualType T = getObjCObjectType(ObjCBuiltinClassTy, nullptr, 0); T = getObjCObjectPointerType(T); - TypeSourceInfo *ClassInfo = getTrivialTypeSourceInfo(T); - ObjCClassDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this), - getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Idents.get("Class"), ClassInfo); + ObjCClassDecl = buildImplicitTypedef(T, "Class"); } - return ObjCClassDecl; } @@ -5724,7 +5772,7 @@ ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const { = ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(), SourceLocation(), &Idents.get("Protocol"), - /*PrevDecl=*/0, + /*PrevDecl=*/nullptr, SourceLocation(), true); } @@ -5737,56 +5785,30 @@ ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const { static TypedefDecl *CreateCharPtrBuiltinVaListDecl(const ASTContext *Context) { // typedef char* __builtin_va_list; - QualType CharPtrType = Context->getPointerType(Context->CharTy); - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(CharPtrType); - - TypedefDecl *VaListTypeDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - return VaListTypeDecl; + QualType T = Context->getPointerType(Context->CharTy); + return Context->buildImplicitTypedef(T, "__builtin_va_list"); } static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) { // typedef void* __builtin_va_list; - QualType VoidPtrType = Context->getPointerType(Context->VoidTy); - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(VoidPtrType); - - TypedefDecl *VaListTypeDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - return VaListTypeDecl; + QualType T = Context->getPointerType(Context->VoidTy); + return Context->buildImplicitTypedef(T, "__builtin_va_list"); } static TypedefDecl * CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { - RecordDecl *VaListTagDecl; + // struct __va_list + RecordDecl *VaListTagDecl = Context->buildImplicitRecord("__va_list"); if (Context->getLangOpts().CPlusPlus) { // namespace std { struct __va_list { NamespaceDecl *NS; NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context), Context->getTranslationUnitDecl(), - /*Inline*/false, SourceLocation(), + /*Inline*/ false, SourceLocation(), SourceLocation(), &Context->Idents.get("std"), - /*PrevDecl*/0); - - VaListTagDecl = CXXRecordDecl::Create(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__va_list")); + /*PrevDecl*/ nullptr); + NS->setImplicit(); VaListTagDecl->setDeclContext(NS); - } else { - // struct __va_list - VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - &Context->Idents.get("__va_list")); } VaListTagDecl->startDefinition(); @@ -5822,8 +5844,8 @@ CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { SourceLocation(), SourceLocation(), &Context->Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, + FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -5834,23 +5856,14 @@ CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { Context->VaListTagTy = VaListTagType; // } __builtin_va_list; - TypedefDecl *VaListTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - Context->getTrivialTypeSourceInfo(VaListTagType)); - - return VaListTypedefDecl; + return Context->buildImplicitTypedef(VaListTagType, "__builtin_va_list"); } static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { // typedef struct __va_list_tag { RecordDecl *VaListTagDecl; - VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - &Context->Idents.get("__va_list_tag")); + VaListTagDecl = Context->buildImplicitRecord("__va_list_tag"); VaListTagDecl->startDefinition(); const size_t NumFields = 5; @@ -5883,8 +5896,8 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { SourceLocation(), SourceLocation(), &Context->Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, + FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -5895,12 +5908,9 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { Context->VaListTagTy = VaListTagType; // } __va_list_tag; - TypedefDecl *VaListTagTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__va_list_tag"), - Context->getTrivialTypeSourceInfo(VaListTagType)); + TypedefDecl *VaListTagTypedefDecl = + Context->buildImplicitTypedef(VaListTagType, "__va_list_tag"); + QualType VaListTagTypedefType = Context->getTypedefType(VaListTagTypedefDecl); @@ -5909,25 +5919,14 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { QualType VaListTagArrayType = Context->getConstantArrayType(VaListTagTypedefType, Size, ArrayType::Normal, 0); - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(VaListTagArrayType); - TypedefDecl *VaListTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - - return VaListTypedefDecl; + return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list"); } static TypedefDecl * CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { // typedef struct __va_list_tag { RecordDecl *VaListTagDecl; - VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - &Context->Idents.get("__va_list_tag")); + VaListTagDecl = Context->buildImplicitRecord("__va_list_tag"); VaListTagDecl->startDefinition(); const size_t NumFields = 4; @@ -5957,8 +5956,8 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { SourceLocation(), SourceLocation(), &Context->Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, + FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -5969,12 +5968,9 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { Context->VaListTagTy = VaListTagType; // } __va_list_tag; - TypedefDecl *VaListTagTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__va_list_tag"), - Context->getTrivialTypeSourceInfo(VaListTagType)); + TypedefDecl *VaListTagTypedefDecl = + Context->buildImplicitTypedef(VaListTagType, "__va_list_tag"); + QualType VaListTagTypedefType = Context->getTypedefType(VaListTagTypedefDecl); @@ -5983,16 +5979,7 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { QualType VaListTagArrayType = Context->getConstantArrayType(VaListTagTypedefType, Size, ArrayType::Normal,0); - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(VaListTagArrayType); - TypedefDecl *VaListTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - - return VaListTypedefDecl; + return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list"); } static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) { @@ -6001,19 +5988,13 @@ static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) { QualType IntArrayType = Context->getConstantArrayType(Context->IntTy, Size, ArrayType::Normal, 0); - TypedefDecl *VaListTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - Context->getTrivialTypeSourceInfo(IntArrayType)); - - return VaListTypedefDecl; + return Context->buildImplicitTypedef(IntArrayType, "__builtin_va_list"); } static TypedefDecl * CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { - RecordDecl *VaListDecl; + // struct __va_list + RecordDecl *VaListDecl = Context->buildImplicitRecord("__va_list"); if (Context->getLangOpts().CPlusPlus) { // namespace std { struct __va_list { NamespaceDecl *NS; @@ -6021,20 +6002,9 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { Context->getTranslationUnitDecl(), /*Inline*/false, SourceLocation(), SourceLocation(), &Context->Idents.get("std"), - /*PrevDecl*/0); - - VaListDecl = CXXRecordDecl::Create(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__va_list")); - + /*PrevDecl*/ nullptr); + NS->setImplicit(); VaListDecl->setDeclContext(NS); - - } else { - // struct __va_list { - VaListDecl = CreateRecordDecl(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - &Context->Idents.get("__va_list")); } VaListDecl->startDefinition(); @@ -6046,8 +6016,8 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { SourceLocation(), &Context->Idents.get("__ap"), Context->getPointerType(Context->VoidTy), - /*TInfo=*/0, - /*BitWidth=*/0, + /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -6057,26 +6027,15 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { VaListDecl->completeDefinition(); // typedef struct __va_list __builtin_va_list; - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(Context->getRecordType(VaListDecl)); - - TypedefDecl *VaListTypeDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - - return VaListTypeDecl; + QualType T = Context->getRecordType(VaListDecl); + return Context->buildImplicitTypedef(T, "__builtin_va_list"); } static TypedefDecl * CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { // typedef struct __va_list_tag { RecordDecl *VaListTagDecl; - VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - &Context->Idents.get("__va_list_tag")); + VaListTagDecl = Context->buildImplicitRecord("__va_list_tag"); VaListTagDecl->startDefinition(); const size_t NumFields = 4; @@ -6106,8 +6065,8 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { SourceLocation(), SourceLocation(), &Context->Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, + FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -6118,12 +6077,8 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { Context->VaListTagTy = VaListTagType; // } __va_list_tag; - TypedefDecl *VaListTagTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__va_list_tag"), - Context->getTrivialTypeSourceInfo(VaListTagType)); + TypedefDecl *VaListTagTypedefDecl = + Context->buildImplicitTypedef(VaListTagType, "__va_list_tag"); QualType VaListTagTypedefType = Context->getTypedefType(VaListTagTypedefDecl); @@ -6132,16 +6087,8 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { QualType VaListTagArrayType = Context->getConstantArrayType(VaListTagTypedefType, Size, ArrayType::Normal,0); - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(VaListTagArrayType); - TypedefDecl *VaListTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - return VaListTypedefDecl; + return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list"); } static TypedefDecl *CreateVaListDecl(const ASTContext *Context, @@ -6169,8 +6116,10 @@ static TypedefDecl *CreateVaListDecl(const ASTContext *Context, } TypedefDecl *ASTContext::getBuiltinVaListDecl() const { - if (!BuiltinVaListDecl) + if (!BuiltinVaListDecl) { BuiltinVaListDecl = CreateVaListDecl(this, Target->getBuiltinVaListKind()); + assert(BuiltinVaListDecl->isImplicit()); + } return BuiltinVaListDecl; } @@ -6227,7 +6176,7 @@ ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, llvm::FoldingSetNodeID ID; QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template); - void *InsertPos = 0; + void *InsertPos = nullptr; QualifiedTemplateName *QTN = QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos); if (!QTN) { @@ -6250,7 +6199,7 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, llvm::FoldingSetNodeID ID; DependentTemplateName::Profile(ID, NNS, Name); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentTemplateName *QTN = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); @@ -6285,8 +6234,8 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, llvm::FoldingSetNodeID ID; DependentTemplateName::Profile(ID, NNS, Operator); - - void *InsertPos = 0; + + void *InsertPos = nullptr; DependentTemplateName *QTN = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); @@ -6317,8 +6266,8 @@ ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param, TemplateName replacement) const { llvm::FoldingSetNodeID ID; SubstTemplateTemplateParmStorage::Profile(ID, param, replacement); - - void *insertPos = 0; + + void *insertPos = nullptr; SubstTemplateTemplateParmStorage *subst = SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos); @@ -6336,8 +6285,8 @@ ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, ASTContext &Self = const_cast<ASTContext &>(*this); llvm::FoldingSetNodeID ID; SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack); - - void *InsertPos = 0; + + void *InsertPos = nullptr; SubstTemplateTemplateParmPackStorage *Subst = SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos); @@ -6454,9 +6403,8 @@ ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, ObjCProtocolDecl *rProto) const { if (declaresSameEntity(lProto, rProto)) return true; - for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(), - E = rProto->protocol_end(); PI != E; ++PI) - if (ProtocolCompatibleWithProtocol(lProto, *PI)) + for (auto *PI : rProto->protocols()) + if (ProtocolCompatibleWithProtocol(lProto, PI)) return true; return false; } @@ -6469,13 +6417,9 @@ bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs, const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>(); assert ((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible"); - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { + for (auto *lhsProto : lhsQID->quals()) { bool match = false; - ObjCProtocolDecl *lhsProto = *I; - for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(), - E = rhsOPT->qual_end(); J != E; ++J) { - ObjCProtocolDecl *rhsProto = *J; + for (auto *rhsProto : rhsOPT->quals()) { if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto)) { match = true; break; @@ -6508,12 +6452,11 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // If the RHS is a unqualified interface pointer "NSString*", // make sure we check the class hierarchy. if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) { - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { + for (auto *I : lhsQID->quals()) { // when comparing an id<P> on lhs with a static type on rhs, // see if static class implements all of id's protocols, directly or // through its super class and categories. - if (!rhsID->ClassImplementsProtocol(*I, true)) + if (!rhsID->ClassImplementsProtocol(I, true)) return false; } } @@ -6521,17 +6464,13 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, return true; } // Both the right and left sides have qualifiers. - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { - ObjCProtocolDecl *lhsProto = *I; + for (auto *lhsProto : lhsQID->quals()) { bool match = false; // when comparing an id<P> on lhs with a static type on rhs, // see if static class implements all of id's protocols, directly or // through its super class and categories. - for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(), - E = rhsOPT->qual_end(); J != E; ++J) { - ObjCProtocolDecl *rhsProto = *J; + for (auto *rhsProto : rhsOPT->quals()) { if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { match = true; @@ -6541,12 +6480,11 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // If the RHS is a qualified interface pointer "NSString<P>*", // make sure we check the class hierarchy. if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) { - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { + for (auto *I : lhsQID->quals()) { // when comparing an id<P> on lhs with a static type on rhs, // see if static class implements all of id's protocols, directly or // through its super class and categories. - if (rhsID->ClassImplementsProtocol(*I, true)) { + if (rhsID->ClassImplementsProtocol(I, true)) { match = true; break; } @@ -6565,9 +6503,7 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, if (const ObjCObjectPointerType *lhsOPT = lhs->getAsObjCInterfacePointerType()) { // If both the right and left sides have qualifiers. - for (ObjCObjectPointerType::qual_iterator I = lhsOPT->qual_begin(), - E = lhsOPT->qual_end(); I != E; ++I) { - ObjCProtocolDecl *lhsProto = *I; + for (auto *lhsProto : lhsOPT->quals()) { bool match = false; // when comparing an id<P> on rhs with a static type on lhs, @@ -6575,9 +6511,7 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // through its super class and categories. // First, lhs protocols in the qualifier list must be found, direct // or indirect in rhs's qualifier list or it is a mismatch. - for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(), - E = rhsQID->qual_end(); J != E; ++J) { - ObjCProtocolDecl *rhsProto = *J; + for (auto *rhsProto : rhsQID->quals()) { if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { match = true; @@ -6598,14 +6532,9 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // assume that it is mismatch. if (LHSInheritedProtocols.empty() && lhsOPT->qual_empty()) return false; - for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I = - LHSInheritedProtocols.begin(), - E = LHSInheritedProtocols.end(); I != E; ++I) { + for (auto *lhsProto : LHSInheritedProtocols) { bool match = false; - ObjCProtocolDecl *lhsProto = (*I); - for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(), - E = rhsQID->qual_end(); J != E; ++J) { - ObjCProtocolDecl *rhsProto = *J; + for (auto *rhsProto : rhsQID->quals()) { if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { match = true; @@ -6798,16 +6727,9 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS, if (SuperClassInheritedProtocols.empty()) return false; - for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(), - LHSPE = LHS->qual_end(); - LHSPI != LHSPE; LHSPI++) { - bool SuperImplementsProtocol = false; - ObjCProtocolDecl *LHSProto = (*LHSPI); - - for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I = - SuperClassInheritedProtocols.begin(), - E = SuperClassInheritedProtocols.end(); I != E; ++I) { - ObjCProtocolDecl *SuperClassProto = (*I); + for (const auto *LHSProto : LHS->quals()) { + bool SuperImplementsProtocol = false; + for (auto *SuperClassProto : SuperClassInheritedProtocols) { if (SuperClassProto->lookupProtocolNamed(LHSProto->getIdentifier())) { SuperImplementsProtocol = true; break; @@ -6821,17 +6743,13 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS, return false; } - for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(), - LHSPE = LHS->qual_end(); - LHSPI != LHSPE; LHSPI++) { + for (const auto *LHSPI : LHS->quals()) { bool RHSImplementsProtocol = false; // If the RHS doesn't implement the protocol on the left, the types // are incompatible. - for (ObjCObjectType::qual_iterator RHSPI = RHS->qual_begin(), - RHSPE = RHS->qual_end(); - RHSPI != RHSPE; RHSPI++) { - if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier())) { + for (auto *RHSPI : RHS->quals()) { + if (RHSPI->lookupProtocolNamed(LHSPI->getIdentifier())) { RHSImplementsProtocol = true; break; } @@ -6891,9 +6809,8 @@ QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType, if (const RecordType *UT = T->getAsUnionType()) { RecordDecl *UD = UT->getDecl(); if (UD->hasAttr<TransparentUnionAttr>()) { - for (RecordDecl::field_iterator it = UD->field_begin(), - itend = UD->field_end(); it != itend; ++it) { - QualType ET = it->getType().getUnqualifiedType(); + for (const auto *I : UD->fields()) { + QualType ET = I->getType().getUnqualifiedType(); QualType MT = mergeTypes(ET, SubType, OfBlockPointer, Unqualified); if (!MT.isNull()) return MT; @@ -6904,11 +6821,11 @@ QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType, return QualType(); } -/// mergeFunctionArgumentTypes - merge two types which appear as function -/// argument types -QualType ASTContext::mergeFunctionArgumentTypes(QualType lhs, QualType rhs, - bool OfBlockPointer, - bool Unqualified) { +/// mergeFunctionParameterTypes - merge two types which appear as function +/// parameter types +QualType ASTContext::mergeFunctionParameterTypes(QualType lhs, QualType rhs, + bool OfBlockPointer, + bool Unqualified) { // GNU extension: two types are compatible if they appear as a function // argument, one of the types is a transparent union type and the other // type is compatible with a union member @@ -6938,23 +6855,23 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, // Check return type QualType retType; if (OfBlockPointer) { - QualType RHS = rbase->getResultType(); - QualType LHS = lbase->getResultType(); + QualType RHS = rbase->getReturnType(); + QualType LHS = lbase->getReturnType(); bool UnqualifiedResult = Unqualified; if (!UnqualifiedResult) UnqualifiedResult = (!RHS.hasQualifiers() && LHS.hasQualifiers()); retType = mergeTypes(LHS, RHS, true, UnqualifiedResult, true); } else - retType = mergeTypes(lbase->getResultType(), rbase->getResultType(), false, + retType = mergeTypes(lbase->getReturnType(), rbase->getReturnType(), false, Unqualified); if (retType.isNull()) return QualType(); if (Unqualified) retType = retType.getUnqualifiedType(); - CanQualType LRetType = getCanonicalType(lbase->getResultType()); - CanQualType RRetType = getCanonicalType(rbase->getResultType()); + CanQualType LRetType = getCanonicalType(lbase->getReturnType()); + CanQualType RRetType = getCanonicalType(rbase->getReturnType()); if (Unqualified) { LRetType = LRetType.getUnqualifiedType(); RRetType = RRetType.getUnqualifiedType(); @@ -6998,11 +6915,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lproto && rproto) { // two C99 style function prototypes assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() && "C++ shouldn't be here"); - unsigned lproto_nargs = lproto->getNumArgs(); - unsigned rproto_nargs = rproto->getNumArgs(); - - // Compatible functions must have the same number of arguments - if (lproto_nargs != rproto_nargs) + // Compatible functions must have the same number of parameters + if (lproto->getNumParams() != rproto->getNumParams()) return QualType(); // Variadic and non-variadic functions aren't compatible @@ -7015,29 +6929,29 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (LangOpts.ObjCAutoRefCount && !FunctionTypesMatchOnNSConsumedAttrs(rproto, lproto)) return QualType(); - - // Check argument compatibility + + // Check parameter type compatibility SmallVector<QualType, 10> types; - for (unsigned i = 0; i < lproto_nargs; i++) { - QualType largtype = lproto->getArgType(i).getUnqualifiedType(); - QualType rargtype = rproto->getArgType(i).getUnqualifiedType(); - QualType argtype = mergeFunctionArgumentTypes(largtype, rargtype, - OfBlockPointer, - Unqualified); - if (argtype.isNull()) return QualType(); - + for (unsigned i = 0, n = lproto->getNumParams(); i < n; i++) { + QualType lParamType = lproto->getParamType(i).getUnqualifiedType(); + QualType rParamType = rproto->getParamType(i).getUnqualifiedType(); + QualType paramType = mergeFunctionParameterTypes( + lParamType, rParamType, OfBlockPointer, Unqualified); + if (paramType.isNull()) + return QualType(); + if (Unqualified) - argtype = argtype.getUnqualifiedType(); - - types.push_back(argtype); + paramType = paramType.getUnqualifiedType(); + + types.push_back(paramType); if (Unqualified) { - largtype = largtype.getUnqualifiedType(); - rargtype = rargtype.getUnqualifiedType(); + lParamType = lParamType.getUnqualifiedType(); + rParamType = rParamType.getUnqualifiedType(); } - - if (getCanonicalType(argtype) != getCanonicalType(largtype)) + + if (getCanonicalType(paramType) != getCanonicalType(lParamType)) allLTypes = false; - if (getCanonicalType(argtype) != getCanonicalType(rargtype)) + if (getCanonicalType(paramType) != getCanonicalType(rParamType)) allRTypes = false; } @@ -7061,20 +6975,19 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, // The only types actually affected are promotable integer // types and floats, which would be passed as a different // type depending on whether the prototype is visible. - unsigned proto_nargs = proto->getNumArgs(); - for (unsigned i = 0; i < proto_nargs; ++i) { - QualType argTy = proto->getArgType(i); - + for (unsigned i = 0, n = proto->getNumParams(); i < n; ++i) { + QualType paramTy = proto->getParamType(i); + // Look at the converted type of enum types, since that is the type used // to pass enum values. - if (const EnumType *Enum = argTy->getAs<EnumType>()) { - argTy = Enum->getDecl()->getIntegerType(); - if (argTy.isNull()) + if (const EnumType *Enum = paramTy->getAs<EnumType>()) { + paramTy = Enum->getDecl()->getIntegerType(); + if (paramTy.isNull()) return QualType(); } - - if (argTy->isPromotableIntegerType() || - getCanonicalType(argTy).getUnqualifiedType() == FloatTy) + + if (paramTy->isPromotableIntegerType() || + getCanonicalType(paramTy).getUnqualifiedType() == FloatTy) return QualType(); } @@ -7083,7 +6996,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionProtoType::ExtProtoInfo EPI = proto->getExtProtoInfo(); EPI.ExtInfo = einfo; - return getFunctionType(retType, proto->getArgTypes(), EPI); + return getFunctionType(retType, proto->getParamTypes(), EPI); } if (allLTypes) return lhs; @@ -7387,18 +7300,16 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs( const FunctionProtoType *FromFunctionType, const FunctionProtoType *ToFunctionType) { - if (FromFunctionType->hasAnyConsumedArgs() != - ToFunctionType->hasAnyConsumedArgs()) + if (FromFunctionType->hasAnyConsumedParams() != + ToFunctionType->hasAnyConsumedParams()) return false; FunctionProtoType::ExtProtoInfo FromEPI = FromFunctionType->getExtProtoInfo(); FunctionProtoType::ExtProtoInfo ToEPI = ToFunctionType->getExtProtoInfo(); - if (FromEPI.ConsumedArguments && ToEPI.ConsumedArguments) - for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs(); - ArgIdx != NumArgs; ++ArgIdx) { - if (FromEPI.ConsumedArguments[ArgIdx] != - ToEPI.ConsumedArguments[ArgIdx]) + if (FromEPI.ConsumedParameters && ToEPI.ConsumedParameters) + for (unsigned i = 0, n = FromFunctionType->getNumParams(); i != n; ++i) { + if (FromEPI.ConsumedParameters[i] != ToEPI.ConsumedParameters[i]) return false; } return true; @@ -7416,10 +7327,10 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { if (RHSCan->isFunctionType()) { if (!LHSCan->isFunctionType()) return QualType(); - QualType OldReturnType = - cast<FunctionType>(RHSCan.getTypePtr())->getResultType(); + QualType OldReturnType = + cast<FunctionType>(RHSCan.getTypePtr())->getReturnType(); QualType NewReturnType = - cast<FunctionType>(LHSCan.getTypePtr())->getResultType(); + cast<FunctionType>(LHSCan.getTypePtr())->getReturnType(); QualType ResReturnType = mergeObjCGCQualifiers(NewReturnType, OldReturnType); if (ResReturnType.isNull()) @@ -7432,7 +7343,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = getFunctionExtInfo(LHS); QualType ResultType = - getFunctionType(OldReturnType, FPT->getArgTypes(), EPI); + getFunctionType(OldReturnType, FPT->getParamTypes(), EPI); return ResultType; } } @@ -7573,6 +7484,19 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, assert(HowLong <= 2 && "Can't have LLLL modifier"); ++HowLong; break; + case 'W': + // This modifier represents int64 type. + assert(HowLong == 0 && "Can't use both 'L' and 'W' modifiers!"); + switch (Context.getTargetInfo().getInt64Type()) { + default: + llvm_unreachable("Unexpected integer type"); + case TargetInfo::SignedLong: + HowLong = 1; + break; + case TargetInfo::SignedLongLong: + HowLong = 2; + break; + } } } @@ -7834,7 +7758,8 @@ QualType ASTContext::GetBuiltinType(unsigned Id, return getFunctionType(ResType, ArgTypes, EPI); } -GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { +static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, + const FunctionDecl *FD) { if (!FD->isExternallyVisible()) return GVA_Internal; @@ -7846,68 +7771,126 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { break; case TSK_ExplicitInstantiationDefinition: - return GVA_ExplicitTemplateInstantiation; + return GVA_StrongODR; + // C++11 [temp.explicit]p10: + // [ Note: The intent is that an inline function that is the subject of + // an explicit instantiation declaration will still be implicitly + // instantiated when used so that the body can be considered for + // inlining, but that no out-of-line copy of the inline function would be + // generated in the translation unit. -- end note ] case TSK_ExplicitInstantiationDeclaration: + return GVA_AvailableExternally; + case TSK_ImplicitInstantiation: - External = GVA_TemplateInstantiation; + External = GVA_DiscardableODR; break; } if (!FD->isInlined()) return External; - if ((!getLangOpts().CPlusPlus && !getLangOpts().MicrosoftMode) || + if ((!Context.getLangOpts().CPlusPlus && !Context.getLangOpts().MSVCCompat && + !FD->hasAttr<DLLExportAttr>()) || FD->hasAttr<GNUInlineAttr>()) { + // FIXME: This doesn't match gcc's behavior for dllexport inline functions. + // GNU or C99 inline semantics. Determine whether this symbol should be // externally visible. if (FD->isInlineDefinitionExternallyVisible()) return External; // C99 inline semantics, where the symbol is not externally visible. - return GVA_C99Inline; + return GVA_AvailableExternally; } - // C++0x [temp.explicit]p9: - // [ Note: The intent is that an inline function that is the subject of - // an explicit instantiation declaration will still be implicitly - // instantiated when used so that the body can be considered for - // inlining, but that no out-of-line copy of the inline function would be - // generated in the translation unit. -- end note ] - if (FD->getTemplateSpecializationKind() - == TSK_ExplicitInstantiationDeclaration) - return GVA_C99Inline; + // Functions specified with extern and inline in -fms-compatibility mode + // forcibly get emitted. While the body of the function cannot be later + // replaced, the function definition cannot be discarded. + if (FD->getMostRecentDecl()->isMSExternInline()) + return GVA_StrongODR; - return GVA_CXXInline; + return GVA_DiscardableODR; } -GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { +static GVALinkage adjustGVALinkageForDLLAttribute(GVALinkage L, const Decl *D) { + // See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx + // dllexport/dllimport on inline functions. + if (D->hasAttr<DLLImportAttr>()) { + if (L == GVA_DiscardableODR || L == GVA_StrongODR) + return GVA_AvailableExternally; + } else if (D->hasAttr<DLLExportAttr>()) { + if (L == GVA_DiscardableODR) + return GVA_StrongODR; + } + return L; +} + +GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { + return adjustGVALinkageForDLLAttribute(basicGVALinkageForFunction(*this, FD), + FD); +} + +static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, + const VarDecl *VD) { if (!VD->isExternallyVisible()) return GVA_Internal; + if (VD->isStaticLocal()) { + GVALinkage StaticLocalLinkage = GVA_DiscardableODR; + const DeclContext *LexicalContext = VD->getParentFunctionOrMethod(); + while (LexicalContext && !isa<FunctionDecl>(LexicalContext)) + LexicalContext = LexicalContext->getLexicalParent(); + + // Let the static local variable inherit it's linkage from the nearest + // enclosing function. + if (LexicalContext) + StaticLocalLinkage = + Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext)); + + // GVA_StrongODR function linkage is stronger than what we need, + // downgrade to GVA_DiscardableODR. + // This allows us to discard the variable if we never end up needing it. + return StaticLocalLinkage == GVA_StrongODR ? GVA_DiscardableODR + : StaticLocalLinkage; + } + + // MSVC treats in-class initialized static data members as definitions. + // By giving them non-strong linkage, out-of-line definitions won't + // cause link errors. + if (Context.isMSStaticDataMemberInlineDefinition(VD)) + return GVA_DiscardableODR; + 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; + return GVA_StrongODR; + + case TSK_ExplicitInstantiationDeclaration: + return GVA_AvailableExternally; case TSK_ImplicitInstantiation: - return GVA_TemplateInstantiation; + return GVA_DiscardableODR; } llvm_unreachable("Invalid Linkage!"); } +GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { + return adjustGVALinkageForDLLAttribute(basicGVALinkageForVariable(*this, VD), + VD); +} + bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (!VD->isFileVarDecl()) return false; + // Global named register variables (GNU extension) are never emitted. + if (VD->getStorageClass() == SC_Register) + return false; } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // We never need to emit an uninstantiated function template. if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) @@ -7954,8 +7937,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // static, static inline, always_inline, and extern inline functions can // always be deferred. Normal inline functions can be deferred in C99/C++. // Implicit template instantiations can also be deferred in C++. - if (Linkage == GVA_Internal || Linkage == GVA_C99Inline || - Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) + if (Linkage == GVA_Internal || Linkage == GVA_AvailableExternally || + Linkage == GVA_DiscardableODR) return false; return true; } @@ -7963,12 +7946,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { const VarDecl *VD = cast<VarDecl>(D); assert(VD->isFileVarDecl() && "Expected file scoped var"); - if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly) + if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly && + !isMSStaticDataMemberInlineDefinition(VD)) return false; // Variables that can be needed in other TUs are required. GVALinkage L = GetGVALinkageForVariable(VD); - if (L != GVA_Internal && L != GVA_TemplateInstantiation) + if (L != GVA_Internal && L != GVA_AvailableExternally && + L != GVA_DiscardableODR) return true; // Variables that have destruction with side-effects are required. @@ -7996,12 +7981,23 @@ bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { return ABI->isNearlyEmpty(RD); } +VTableContextBase *ASTContext::getVTableContext() { + if (!VTContext.get()) { + if (Target->getCXXABI().isMicrosoft()) + VTContext.reset(new MicrosoftVTableContext(*this)); + else + VTContext.reset(new ItaniumVTableContext(*this)); + } + return VTContext.get(); +} + MangleContext *ASTContext::createMangleContext() { switch (Target->getCXXABI().getKind()) { case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericItanium: case TargetCXXABI::GenericARM: case TargetCXXABI::iOS: + case TargetCXXABI::iOS64: return ItaniumMangleContext::create(*this, getDiagnostics()); case TargetCXXABI::Microsoft: return MicrosoftMangleContext::create(*this, getDiagnostics()); @@ -8071,6 +8067,17 @@ unsigned ASTContext::getManglingNumber(const NamedDecl *ND) const { return I != MangleNumbers.end() ? I->second : 1; } +void ASTContext::setStaticLocalNumber(const VarDecl *VD, unsigned Number) { + if (Number > 1) + StaticLocalNumbers[VD] = Number; +} + +unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const { + llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = + StaticLocalNumbers.find(VD); + return I != StaticLocalNumbers.end() ? I->second : 1; +} + MangleNumberingContext & ASTContext::getManglingNumberContext(const DeclContext *DC) { assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C. @@ -8105,7 +8112,7 @@ ASTContext::getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, llvm::DenseMap<const MaterializeTemporaryExpr *, APValue>::iterator I = MaterializedTemporaryValues.find(E); - return I == MaterializedTemporaryValues.end() ? 0 : &I->second; + return I == MaterializedTemporaryValues.end() ? nullptr : &I->second; } bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { @@ -8168,18 +8175,45 @@ namespace { template <typename T> bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) { - if (Node == NULL) + if (!Node) 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. + if (ParentStack.size() > 0) { + // FIXME: Currently we add the same parent multiple times, but only + // when no memoization data is available for the type. + // For example when we visit all subexpressions of template + // instantiations; this is suboptimal, but 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()); + auto &NodeOrVector = (*Parents)[Node]; + if (NodeOrVector.isNull()) { + NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back()); + } else { + if (NodeOrVector.template is<ast_type_traits::DynTypedNode *>()) { + auto *Node = + NodeOrVector.template get<ast_type_traits::DynTypedNode *>(); + auto *Vector = new ASTContext::ParentVector(1, *Node); + NodeOrVector = Vector; + delete Node; + } + assert(NodeOrVector.template is<ASTContext::ParentVector *>()); + + auto *Vector = + NodeOrVector.template get<ASTContext::ParentVector *>(); + // Skip duplicates for types that have memoization data. + // We must check that the type has memoization data before calling + // std::find() because DynTypedNode::operator== can't compare all + // types. + bool Found = ParentStack.back().getMemoizationData() && + std::find(Vector->begin(), Vector->end(), + ParentStack.back()) != Vector->end(); + if (!Found) + Vector->push_back(ParentStack.back()); + } + } ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node)); bool Result = (this ->* traverse) (Node); ParentStack.pop_back(); @@ -8217,7 +8251,11 @@ ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { if (I == AllParents->end()) { return ParentVector(); } - return I->second; + if (I->second.is<ast_type_traits::DynTypedNode *>()) { + return ParentVector(1, *I->second.get<ast_type_traits::DynTypedNode *>()); + } + const auto &Parents = *I->second.get<ParentVector *>(); + return ParentVector(Parents.begin(), Parents.end()); } bool @@ -8230,8 +8268,7 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, if (MethodDecl->getObjCDeclQualifier() != MethodImpl->getObjCDeclQualifier()) return false; - if (!hasSameType(MethodDecl->getResultType(), - MethodImpl->getResultType())) + if (!hasSameType(MethodDecl->getReturnType(), MethodImpl->getReturnType())) return false; if (MethodDecl->param_size() != MethodImpl->param_size()) @@ -8251,3 +8288,12 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, return (MethodDecl->isVariadic() == MethodImpl->isVariadic()); } + +// Explicitly instantiate this in case a Redeclarable<T> is used from a TU that +// doesn't include ASTContext.h +template +clang::LazyGenerationalUpdatePtr< + const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::ValueType +clang::LazyGenerationalUpdatePtr< + const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::makeValue( + const clang::ASTContext &Ctx, Decl *Value); diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index fce8f64..8c8b1df 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" @@ -51,6 +53,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { QT = AT->desugar(); continue; } + // ...or an adjusted type... + if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) { + QT = AT->desugar(); + continue; + } // ... or an auto type. if (const AutoType *AT = dyn_cast<AutoType>(Ty)) { if (!AT->isSugared()) @@ -155,9 +162,8 @@ break; \ /// diagnostic message static std::string ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, - const DiagnosticsEngine::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, - ArrayRef<intptr_t> QualTypeVals) { + ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, + ArrayRef<intptr_t> QualTypeVals) { // FIXME: Playing with std::string is really slow. bool ForceAKA = false; QualType CanTy = Ty.getCanonicalType(); @@ -195,7 +201,7 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, // Check to see if we already desugared this type in this // diagnostic. If so, don't do it again. bool Repeated = false; - for (unsigned i = 0; i != NumPrevArgs; ++i) { + for (unsigned i = 0, e = PrevArgs.size(); i != e; ++i) { // TODO: Handle ak_declcontext case. if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) { void *Ptr = (void*)PrevArgs[i].second; @@ -222,6 +228,20 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, return S; } } + + // Give some additional info on vector types. These are either not desugared + // or displaying complex __attribute__ expressions so add details of the + // type and element count. + if (Ty->isVectorType()) { + const VectorType *VTy = Ty->getAs<VectorType>(); + std::string DecoratedString; + llvm::raw_string_ostream OS(DecoratedString); + const char *Values = VTy->getNumElements() > 1 ? "values" : "value"; + OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '" + << VTy->getElementType().getAsString(Context.getPrintingPolicy()) + << "' " << Values << ")"; + return OS.str(); + } } S = "'" + S + "'"; @@ -236,12 +256,9 @@ static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, void clang::FormatASTNodeDiagnosticArgument( DiagnosticsEngine::ArgumentKind Kind, intptr_t Val, - const char *Modifier, - unsigned ModLen, - const char *Argument, - unsigned ArgLen, - const DiagnosticsEngine::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, + StringRef Modifier, + StringRef Argument, + ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, SmallVectorImpl<char> &Output, void *Cookie, ArrayRef<intptr_t> QualTypeVals) { @@ -276,28 +293,26 @@ void clang::FormatASTNodeDiagnosticArgument( // Attempting to do a template diff on non-templates. Set the variables // and continue with regular type printing of the appropriate type. Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType; - ModLen = 0; - ArgLen = 0; + Modifier = StringRef(); + Argument = StringRef(); // Fall through } case DiagnosticsEngine::ak_qualtype: { - assert(ModLen == 0 && ArgLen == 0 && + assert(Modifier.empty() && Argument.empty() && "Invalid modifier for QualType argument"); QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); - OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs, - QualTypeVals); + OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, QualTypeVals); NeedQuotes = false; break; } case DiagnosticsEngine::ak_declarationname: { - if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0) + if (Modifier == "objcclass" && Argument.empty()) OS << '+'; - else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) - && ArgLen==0) + else if (Modifier == "objcinstance" && Argument.empty()) OS << '-'; else - assert(ModLen == 0 && ArgLen == 0 && + assert(Modifier.empty() && Argument.empty() && "Invalid modifier for DeclarationName argument"); OS << DeclarationName::getFromOpaqueInteger(Val); @@ -305,10 +320,10 @@ void clang::FormatASTNodeDiagnosticArgument( } case DiagnosticsEngine::ak_nameddecl: { bool Qualified; - if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0) + if (Modifier == "q" && Argument.empty()) Qualified = true; else { - assert(ModLen == 0 && ArgLen == 0 && + assert(Modifier.empty() && Argument.empty() && "Invalid modifier for NamedDecl* argument"); Qualified = false; } @@ -325,7 +340,8 @@ void clang::FormatASTNodeDiagnosticArgument( case DiagnosticsEngine::ak_declcontext: { DeclContext *DC = reinterpret_cast<DeclContext *> (Val); assert(DC && "Should never have a null declaration context"); - + NeedQuotes = false; + if (DC->isTranslationUnit()) { // FIXME: Get these strings from some localized place if (Context.getLangOpts().CPlusPlus) @@ -335,10 +351,17 @@ void clang::FormatASTNodeDiagnosticArgument( } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { OS << ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type), - PrevArgs, NumPrevArgs, - QualTypeVals); + PrevArgs, QualTypeVals); } else { // FIXME: Get these strings from some localized place + if (isa<BlockDecl>(DC)) { + OS << "block literal"; + break; + } + if (isLambdaCallOperator(DC)) { + OS << "lambda expression"; + break; + } NamedDecl *ND = cast<NamedDecl>(DC); if (isa<NamespaceDecl>(ND)) OS << "namespace "; @@ -351,9 +374,16 @@ void clang::FormatASTNodeDiagnosticArgument( ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true); OS << '\''; } + break; + } + case DiagnosticsEngine::ak_attr: { + const Attr *At = reinterpret_cast<Attr *>(Val); + assert(At && "Received null Attr object!"); + OS << '\'' << At->getSpelling() << '\''; NeedQuotes = false; break; } + } OS.flush(); @@ -442,6 +472,9 @@ class TemplateDiff { /// FromExpr, ToExpr - The expression arguments. Expr *FromExpr, *ToExpr; + /// FromNullPtr, ToNullPtr - If the template argument is a nullptr + bool FromNullPtr, ToNullPtr; + /// FromTD, ToTD - The template decl for template template /// arguments or the type arguments that are templates. TemplateDecl *FromTD, *ToTD; @@ -470,10 +503,12 @@ class TemplateDiff { DiffNode(unsigned ParentNode = 0) : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode), - FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0), - IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0), - ToValueDecl(0), FromAddressOf(false), ToAddressOf(false), - FromDefault(false), ToDefault(false), Same(false) { } + FromType(), ToType(), FromExpr(nullptr), ToExpr(nullptr), + FromNullPtr(false), ToNullPtr(false), + FromTD(nullptr), ToTD(nullptr), IsValidFromInt(false), + IsValidToInt(false), FromValueDecl(nullptr), ToValueDecl(nullptr), + FromAddressOf(false), ToAddressOf(false), FromDefault(false), + ToDefault(false), Same(false) {} }; /// FlatTree - A flattened tree used to store the DiffNodes. @@ -543,6 +578,12 @@ class TemplateDiff { FlatTree[CurrentNode].Same = Same; } + /// SetNullPtr - Sets the NullPtr flags of the current node. + void SetNullPtr(bool FromNullPtr, bool ToNullPtr) { + FlatTree[CurrentNode].FromNullPtr = FromNullPtr; + FlatTree[CurrentNode].ToNullPtr = ToNullPtr; + } + /// SetDefault - Sets FromDefault and ToDefault flags of the current node. void SetDefault(bool FromDefault, bool ToDefault) { FlatTree[CurrentNode].FromDefault = FromDefault; @@ -665,6 +706,16 @@ class TemplateDiff { return FlatTree[ReadNode].NextNode != 0; } + /// FromNullPtr - Returns true if the from argument is null. + bool FromNullPtr() { + return FlatTree[ReadNode].FromNullPtr; + } + + /// ToNullPtr - Returns true if the to argument is null. + bool ToNullPtr() { + return FlatTree[ReadNode].ToNullPtr; + } + /// FromDefault - Return true if the from argument is the default. bool FromDefault() { return FlatTree[ReadNode].FromDefault; @@ -718,7 +769,7 @@ class TemplateDiff { TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) : TST(TST), DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())), - Index(0), CurrentTA(0), EndTA(0) { + Index(0), CurrentTA(nullptr), EndTA(nullptr) { if (isEnd()) return; // Set to first template argument. If not a parameter pack, done. @@ -809,13 +860,13 @@ class TemplateDiff { const RecordType *RT = Ty->getAs<RecordType>(); if (!RT) - return 0; + return nullptr; const ClassTemplateSpecializationDecl *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); if (!CTSD) - return 0; + return nullptr; Ty = Context.getTemplateSpecializationType( TemplateName(CTSD->getSpecializedTemplate()), @@ -887,9 +938,9 @@ class TemplateDiff { // Handle Expressions if (NonTypeTemplateParmDecl *DefaultNTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamND)) { - Expr *FromExpr = 0, *ToExpr = 0; + Expr *FromExpr = nullptr, *ToExpr = nullptr; llvm::APSInt FromInt, ToInt; - ValueDecl *FromValueDecl = 0, *ToValueDecl = 0; + ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr; unsigned ParamWidth = 128; // Safe default if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) ParamWidth = Context.getIntWidth(DefaultNTTPD->getType()); @@ -903,6 +954,10 @@ class TemplateDiff { bool HasToValueDecl = !ToIter.isEnd() && ToIter->getKind() == TemplateArgument::Declaration; + bool FromNullPtr = !FromIter.isEnd() && + FromIter->getKind() == TemplateArgument::NullPtr; + bool ToNullPtr = + !ToIter.isEnd() && ToIter->getKind() == TemplateArgument::NullPtr; assert(((!HasFromInt && !HasToInt) || (!HasFromValueDecl && !HasToValueDecl)) && @@ -912,41 +967,54 @@ class TemplateDiff { FromInt = FromIter->getAsIntegral(); else if (HasFromValueDecl) FromValueDecl = FromIter->getAsDecl(); - else + else if (!FromNullPtr) FromExpr = GetExpr(FromIter, DefaultNTTPD); if (HasToInt) ToInt = ToIter->getAsIntegral(); else if (HasToValueDecl) ToValueDecl = ToIter->getAsDecl(); - else + else if (!ToNullPtr) ToExpr = GetExpr(ToIter, DefaultNTTPD); + bool TemplateArgumentIsPointerType = + DefaultNTTPD->getType()->isPointerType(); + if (FromExpr && TemplateArgumentIsPointerType) { + FromNullPtr = CheckForNullPtr(FromExpr); + } + if (ToExpr && TemplateArgumentIsPointerType) { + ToNullPtr = CheckForNullPtr(ToExpr); + } + if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) { Tree.SetNode(FromExpr, ToExpr); Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr); if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) { if (FromExpr) - FromInt = GetInt(FromIter, FromExpr); + HasFromInt = GetInt(FromIter, FromExpr, FromInt); if (ToExpr) - ToInt = GetInt(ToIter, ToExpr); - Tree.SetNode(FromInt, ToInt, FromExpr, ToExpr); + HasToInt = GetInt(ToIter, ToExpr, ToInt); + } + if (HasFromInt && HasToInt) { + Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); Tree.SetKind(DiffTree::Integer); + } else if (HasFromInt || HasToInt) { + Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); + Tree.SetSame(false); + Tree.SetKind(DiffTree::Integer); } else { - Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr)); + Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr) || + (FromNullPtr && ToNullPtr)); + Tree.SetNullPtr(FromNullPtr, ToNullPtr); Tree.SetKind(DiffTree::Expression); } } else if (HasFromInt || HasToInt) { - if (!HasFromInt && FromExpr) { - FromInt = GetInt(FromIter, FromExpr); - HasFromInt = true; - } - if (!HasToInt && ToExpr) { - ToInt = GetInt(ToIter, ToExpr); - HasToInt = true; - } + if (!HasFromInt && FromExpr) + HasFromInt = GetInt(FromIter, FromExpr, FromInt); + if (!HasToInt && ToExpr) + HasToInt = GetInt(ToIter, ToExpr, ToInt); Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); Tree.SetDefault(FromIter.isEnd() && HasFromInt, @@ -958,12 +1026,36 @@ class TemplateDiff { if (!HasToValueDecl && ToExpr) ToValueDecl = GetValueDecl(ToIter, ToExpr); QualType ArgumentType = DefaultNTTPD->getType(); - bool FromAddressOf = FromValueDecl && - !ArgumentType->isReferenceType() && - !FromValueDecl->getType()->isArrayType(); - bool ToAddressOf = ToValueDecl && - !ArgumentType->isReferenceType() && - !ToValueDecl->getType()->isArrayType(); + bool FromAddressOf = false; + if (FromValueDecl) { + if (FromExpr) { + if (UnaryOperator *UO = + dyn_cast<UnaryOperator>(FromExpr->IgnoreParens())) { + if (UO->getOpcode() == UO_AddrOf) + FromAddressOf = true; + } + } else { + if (!ArgumentType->isReferenceType()) { + FromAddressOf = true; + } + } + } + bool ToAddressOf = false; + if (ToValueDecl) { + if (ToExpr) { + if (UnaryOperator *UO = + dyn_cast<UnaryOperator>(ToExpr->IgnoreParens())) { + if (UO->getOpcode() == UO_AddrOf) { + ToAddressOf = true; + } + } + } else { + if (!ArgumentType->isReferenceType()) { + ToAddressOf = true; + } + } + } + Tree.SetNullPtr(FromNullPtr, ToNullPtr); Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); Tree.SetSame(FromValueDecl && ToValueDecl && FromValueDecl->getCanonicalDecl() == @@ -984,6 +1076,7 @@ class TemplateDiff { Tree.SetSame( FromDecl && ToDecl && FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl()); + Tree.SetDefault(FromIter.isEnd() && FromDecl, ToIter.isEnd() && ToDecl); Tree.SetKind(DiffTree::TemplateTemplate); } @@ -1072,7 +1165,7 @@ class TemplateDiff { /// GetExpr - Retrieves the template expression argument, including default /// arguments. Expr *GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD) { - Expr *ArgExpr = 0; + Expr *ArgExpr = nullptr; bool isVariadic = DefaultNTTPD->isParameterPack(); if (!Iter.isEnd()) @@ -1090,20 +1183,28 @@ class TemplateDiff { /// GetInt - Retrieves the template integer argument, including evaluating /// default arguments. - llvm::APInt GetInt(const TSTiterator &Iter, Expr *ArgExpr) { + bool GetInt(const TSTiterator &Iter, Expr *ArgExpr, llvm::APInt &Int) { // Default, value-depenedent expressions require fetching - // from the desugared TemplateArgument - if (Iter.isEnd() && ArgExpr->isValueDependent()) + // from the desugared TemplateArgument, otherwise expression needs to + // be evaluatable. + if (Iter.isEnd() && ArgExpr->isValueDependent()) { switch (Iter.getDesugar().getKind()) { case TemplateArgument::Integral: - return Iter.getDesugar().getAsIntegral(); + Int = Iter.getDesugar().getAsIntegral(); + return true; case TemplateArgument::Expression: ArgExpr = Iter.getDesugar().getAsExpr(); - return ArgExpr->EvaluateKnownConstInt(Context); + Int = ArgExpr->EvaluateKnownConstInt(Context); + return true; default: - assert(0 && "Unexpected template argument kind"); + llvm_unreachable("Unexpected template argument kind"); } - return ArgExpr->EvaluateKnownConstInt(Context); + } else if (ArgExpr->isEvaluatable(Context)) { + Int = ArgExpr->EvaluateKnownConstInt(Context); + return true; + } + + return false; } /// GetValueDecl - Retrieves the template Decl argument, including @@ -1119,16 +1220,40 @@ class TemplateDiff { ArgExpr = Iter.getDesugar().getAsExpr(); return cast<DeclRefExpr>(ArgExpr)->getDecl(); default: - assert(0 && "Unexpected template argument kind"); + llvm_unreachable("Unexpected template argument kind"); } DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr); if (!DRE) { - DRE = cast<DeclRefExpr>(cast<UnaryOperator>(ArgExpr)->getSubExpr()); + UnaryOperator *UO = dyn_cast<UnaryOperator>(ArgExpr->IgnoreParens()); + if (!UO) + return nullptr; + DRE = cast<DeclRefExpr>(UO->getSubExpr()); } return DRE->getDecl(); } + /// CheckForNullPtr - returns true if the expression can be evaluated as + /// a null pointer + bool CheckForNullPtr(Expr *E) { + assert(E && "Expected expression"); + + E = E->IgnoreParenCasts(); + if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + return true; + + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); + if (!DRE) + return false; + + VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); + if (!VD || !VD->hasInit()) + return false; + + return VD->getInit()->IgnoreParenCasts()->isNullPointerConstant( + Context, Expr::NPC_ValueDependentIsNull); + } + /// GetTemplateDecl - Retrieves the template template arguments, including /// default arguments. TemplateDecl *GetTemplateDecl(const TSTiterator &Iter, @@ -1136,7 +1261,7 @@ class TemplateDiff { bool isVariadic = DefaultTTPD->isParameterPack(); TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument(); - TemplateDecl *DefaultTD = 0; + TemplateDecl *DefaultTD = nullptr; if (TA.getKind() != TemplateArgument::Null) DefaultTD = TA.getAsTemplate().getAsTemplateDecl(); @@ -1145,7 +1270,7 @@ class TemplateDiff { if (!isVariadic) return DefaultTD; - return 0; + return nullptr; } /// IsSameConvertedInt - Returns true if both integers are equal when @@ -1166,11 +1291,8 @@ class TemplateDiff { if (!FromExpr || !ToExpr) return false; - FromExpr = FromExpr->IgnoreParens(); - ToExpr = ToExpr->IgnoreParens(); - - DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr), - *ToDRE = dyn_cast<DeclRefExpr>(ToExpr); + DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr->IgnoreParens()), + *ToDRE = dyn_cast<DeclRefExpr>(ToExpr->IgnoreParens()); if (FromDRE || ToDRE) { if (!FromDRE || !ToDRE) @@ -1180,8 +1302,12 @@ class TemplateDiff { Expr::EvalResult FromResult, ToResult; if (!FromExpr->EvaluateAsRValue(FromResult, Context) || - !ToExpr->EvaluateAsRValue(ToResult, Context)) - return false; + !ToExpr->EvaluateAsRValue(ToResult, Context)) { + llvm::FoldingSetNodeID FromID, ToID; + FromExpr->Profile(FromID, Context, true); + ToExpr->Profile(ToID, Context, true); + return FromID == ToID; + } APValue &FromVal = FromResult.Val; APValue &ToVal = ToResult.Val; @@ -1235,8 +1361,8 @@ class TemplateDiff { case DiffTree::Expression: { Expr *FromExpr, *ToExpr; Tree.GetNode(FromExpr, ToExpr); - PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), - Tree.NodeIsSame()); + PrintExpr(FromExpr, ToExpr, Tree.FromNullPtr(), Tree.ToNullPtr(), + Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } case DiffTree::TemplateTemplate: { @@ -1262,7 +1388,8 @@ class TemplateDiff { bool FromAddressOf, ToAddressOf; Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf, - Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); + Tree.FromNullPtr(), Tree.ToNullPtr(), Tree.FromDefault(), + Tree.ToDefault(), Tree.NodeIsSame()); return; } case DiffTree::Template: { @@ -1341,7 +1468,7 @@ class TemplateDiff { "Only one template argument may be missing."); if (Same) { - OS << FromType.getAsString(); + OS << FromType.getAsString(Policy); return; } @@ -1349,22 +1476,22 @@ class TemplateDiff { FromType.getLocalUnqualifiedType() == ToType.getLocalUnqualifiedType()) { Qualifiers FromQual = FromType.getLocalQualifiers(), - ToQual = ToType.getLocalQualifiers(), - CommonQual; + ToQual = ToType.getLocalQualifiers(); PrintQualifiers(FromQual, ToQual); FromType.getLocalUnqualifiedType().print(OS, Policy); return; } std::string FromTypeStr = FromType.isNull() ? "(no argument)" - : FromType.getAsString(); + : FromType.getAsString(Policy); std::string ToTypeStr = ToType.isNull() ? "(no argument)" - : ToType.getAsString(); + : ToType.getAsString(Policy); // Switch to canonical typename if it is better. // TODO: merge this with other aka printing above. if (FromTypeStr == ToTypeStr) { - std::string FromCanTypeStr = FromType.getCanonicalType().getAsString(); - std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(); + std::string FromCanTypeStr = + FromType.getCanonicalType().getAsString(Policy); + std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(Policy); if (FromCanTypeStr != ToCanTypeStr) { FromTypeStr = FromCanTypeStr; ToTypeStr = ToCanTypeStr; @@ -1388,36 +1515,41 @@ class TemplateDiff { /// PrintExpr - Prints out the expr template arguments, highlighting argument /// differences. - void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, - bool FromDefault, bool ToDefault, bool Same) { + void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromNullPtr, + bool ToNullPtr, bool FromDefault, bool ToDefault, bool Same) { assert((FromExpr || ToExpr) && "Only one template argument may be missing."); if (Same) { - PrintExpr(FromExpr); + PrintExpr(FromExpr, FromNullPtr); } else if (!PrintTree) { OS << (FromDefault ? "(default) " : ""); Bold(); - PrintExpr(FromExpr); + PrintExpr(FromExpr, FromNullPtr); Unbold(); } else { OS << (FromDefault ? "[(default) " : "["); Bold(); - PrintExpr(FromExpr); + PrintExpr(FromExpr, FromNullPtr); Unbold(); OS << " != " << (ToDefault ? "(default) " : ""); Bold(); - PrintExpr(ToExpr); + PrintExpr(ToExpr, ToNullPtr); Unbold(); OS << ']'; } } /// PrintExpr - Actual formatting and printing of expressions. - void PrintExpr(const Expr *E) { - if (!E) - OS << "(no argument)"; - else - E->printPretty(OS, 0, Policy); return; + void PrintExpr(const Expr *E, bool NullPtr = false) { + if (E) { + E->printPretty(OS, nullptr, Policy); + return; + } + if (NullPtr) { + OS << "nullptr"; + return; + } + OS << "(no argument)"; } /// PrintTemplateTemplate - Handles printing of template template arguments, @@ -1487,6 +1619,8 @@ class TemplateDiff { Bold(); } OS << Val.toString(10); + } else if (E) { + PrintExpr(E); } else { OS << "(no argument)"; } @@ -1507,35 +1641,46 @@ class TemplateDiff { return true; } + void PrintValueDecl(ValueDecl *VD, bool AddressOf, bool NullPtr) { + if (VD) { + if (AddressOf) + OS << "&"; + OS << VD->getName(); + return; + } + + if (NullPtr) { + OS << "nullptr"; + return; + } + + OS << "(no argument)"; + } + /// PrintDecl - Handles printing of Decl arguments, highlighting /// argument differences. void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, - bool FromAddressOf, bool ToAddressOf, bool FromDefault, - bool ToDefault, bool Same) { - assert((FromValueDecl || ToValueDecl) && + bool FromAddressOf, bool ToAddressOf, bool FromNullPtr, + bool ToNullPtr, bool FromDefault, bool ToDefault, + bool Same) { + assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) && "Only one Decl argument may be NULL"); if (Same) { - OS << FromValueDecl->getName(); + PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); } else if (!PrintTree) { OS << (FromDefault ? "(default) " : ""); Bold(); - if (FromAddressOf) - OS << "&"; - OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); + PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); Unbold(); } else { OS << (FromDefault ? "[(default) " : "["); Bold(); - if (FromAddressOf) - OS << "&"; - OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); + PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); Unbold(); OS << " != " << (ToDefault ? "(default) " : ""); Bold(); - if (ToAddressOf) - OS << "&"; - OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)"); + PrintValueDecl(ToValueDecl, ToAddressOf, ToNullPtr); Unbold(); OS << ']'; } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp index 670fd0e..df7a2cb 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp @@ -149,11 +149,43 @@ namespace { } }; + class ChildDumper { + ASTDumper &Dumper; + + const Decl *Prev; + bool PrevRef; + public: + ChildDumper(ASTDumper &Dumper) : Dumper(Dumper), Prev(nullptr) {} + ~ChildDumper() { + if (Prev) { + Dumper.lastChild(); + dump(nullptr); + } + } + + // FIXME: This should take an arbitrary callable as the dumping action. + void dump(const Decl *D, bool Ref = false) { + if (Prev) { + if (PrevRef) + Dumper.dumpDeclRef(Prev); + else + Dumper.dumpDecl(Prev); + } + Prev = D; + PrevRef = Ref; + } + void dumpRef(const Decl *D) { dump(D, true); } + + // Give up ownership of the children of the node. By calling this, + // the caller takes back responsibility for calling lastChild(). + void release() { dump(nullptr); } + }; + public: ASTDumper(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM) : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false), - LastLocFilename(""), LastLocLine(~0U), FC(0), + LastLocFilename(""), LastLocLine(~0U), FC(nullptr), ShowColors(SM && SM->getDiagnostics().getShowColors()) { } ASTDumper(raw_ostream &OS, const CommandTraits *Traits, @@ -184,7 +216,7 @@ namespace { void dumpBareType(QualType T); void dumpType(QualType T); void dumpBareDeclRef(const Decl *Node); - void dumpDeclRef(const Decl *Node, const char *Label = 0); + void dumpDeclRef(const Decl *Node, const char *Label = nullptr); void dumpName(const NamedDecl *D); bool hasNodes(const DeclContext *DC); void dumpDeclContext(const DeclContext *DC); @@ -222,6 +254,13 @@ namespace { void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D); void VisitCXXRecordDecl(const CXXRecordDecl *D); void VisitStaticAssertDecl(const StaticAssertDecl *D); + template<typename SpecializationDecl> + void VisitTemplateDeclSpecialization(ChildDumper &Children, + const SpecializationDecl *D, + bool DumpExplicitInst, + bool DumpRefOnly); + template<typename TemplateDecl> + void VisitTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst); void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); void VisitClassTemplateDecl(const ClassTemplateDecl *D); void VisitClassTemplateSpecializationDecl( @@ -276,6 +315,7 @@ namespace { void VisitIntegerLiteral(const IntegerLiteral *Node); void VisitFloatingLiteral(const FloatingLiteral *Node); void VisitStringLiteral(const StringLiteral *Str); + void VisitInitListExpr(const InitListExpr *ILE); void VisitUnaryOperator(const UnaryOperator *Node); void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node); void VisitMemberExpr(const MemberExpr *Node); @@ -405,6 +445,9 @@ void ASTDumper::dumpPointer(const void *Ptr) { } void ASTDumper::dumpLocation(SourceLocation Loc) { + if (!SM) + return; + ColorScope Color(*this, LocationColor); SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); @@ -511,17 +554,14 @@ bool ASTDumper::hasNodes(const DeclContext *DC) { void ASTDumper::dumpDeclContext(const DeclContext *DC) { if (!DC) return; - bool HasUndeserializedDecls = DC->hasExternalLexicalStorage(); - for (DeclContext::decl_iterator I = DC->noload_decls_begin(), - E = DC->noload_decls_end(); - I != E; ++I) { - DeclContext::decl_iterator Next = I; - ++Next; - if (Next == E && !HasUndeserializedDecls) - lastChild(); - dumpDecl(*I); - } - if (HasUndeserializedDecls) { + + ChildDumper Children(*this); + for (auto *D : DC->noload_decls()) + Children.dump(D); + + if (DC->hasExternalLexicalStorage()) { + Children.release(); + lastChild(); IndentScope Indent(*this); ColorScope Color(*this, UndeserializedColor); @@ -580,6 +620,7 @@ void ASTDumper::dumpAttr(const Attr *A) { IndentScope Indent(*this); { ColorScope Color(*this, AttrColor); + switch (A->getKind()) { #define ATTR(X) case attr::X: OS << #X; break; #include "clang/Basic/AttrList.inc" @@ -589,6 +630,10 @@ void ASTDumper::dumpAttr(const Attr *A) { } dumpPointer(A); dumpSourceRange(A->getRange()); + if (A->isInherited()) + OS << " Inherited"; + if (A->isImplicit()) + OS << " Implicit"; #include "clang/AST/AttrDump.inc" } @@ -753,13 +798,23 @@ void ASTDumper::dumpDecl(const Decl *D) { OS << " parent " << cast<Decl>(D->getDeclContext()); dumpPreviousDecl(OS, D); dumpSourceRange(D->getSourceRange()); + OS << ' '; + dumpLocation(D->getLocation()); if (Module *M = D->getOwningModule()) OS << " in " << M->getFullModuleName(); if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) if (ND->isHidden()) OS << " hidden"; + if (D->isImplicit()) + OS << " implicit"; + if (D->isUsed()) + OS << " used"; + else if (D->isReferenced()) + OS << " referenced"; + if (D->isInvalidDecl()) + OS << " invalid"; - bool HasAttrs = D->attr_begin() != D->attr_end(); + bool HasAttrs = D->hasAttrs(); const FullComment *Comment = D->getASTContext().getLocalCommentForDeclUncached(D); // Decls within functions are visited by the body @@ -781,9 +836,6 @@ void ASTDumper::dumpDecl(const Decl *D) { lastChild(); dumpFullComment(Comment); - if (D->isInvalidDecl()) - OS << " invalid"; - setMoreChildren(false); if (HasDeclContext) dumpDeclContext(cast<DeclContext>(D)); @@ -835,13 +887,10 @@ void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) { void ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) { dumpName(D); dumpType(D->getType()); - for (IndirectFieldDecl::chain_iterator I = D->chain_begin(), - E = D->chain_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); - dumpDeclRef(*I); - } + + ChildDumper Children(*this); + for (auto *Child : D->chain()) + Children.dumpRef(Child); } void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { @@ -975,6 +1024,11 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) { if (D->isNRVOVariable()) OS << " nrvo"; if (D->hasInit()) { + switch (D->getInitStyle()) { + case VarDecl::CInit: OS << " cinit"; break; + case VarDecl::CallInit: OS << " callinit"; break; + case VarDecl::ListInit: OS << " listinit"; break; + } lastChild(); dumpStmt(D->getInit()); } @@ -1027,15 +1081,13 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { if (!D->isCompleteDefinition()) return; - for (CXXRecordDecl::base_class_const_iterator I = D->bases_begin(), - E = D->bases_end(); - I != E; ++I) { + for (const auto &I : D->bases()) { IndentScope Indent(*this); - if (I->isVirtual()) + if (I.isVirtual()) OS << "virtual "; - dumpAccessSpecifier(I->getAccessSpecifier()); - dumpType(I->getType()); - if (I->isPackExpansion()) + dumpAccessSpecifier(I.getAccessSpecifier()); + dumpType(I.getType()); + if (I.isPackExpansion()) OS << "..."; } } @@ -1046,63 +1098,69 @@ void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) { dumpStmt(D->getMessage()); } -void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { - dumpName(D); - dumpTemplateParameters(D->getTemplateParameters()); - dumpDecl(D->getTemplatedDecl()); - for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(), - E = D->spec_end(); - I != E; ++I) { - FunctionTemplateDecl::spec_iterator Next = I; - ++Next; - if (Next == E) - lastChild(); - switch (I->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: +template<typename SpecializationDecl> +void ASTDumper::VisitTemplateDeclSpecialization(ChildDumper &Children, + const SpecializationDecl *D, + bool DumpExplicitInst, + bool DumpRefOnly) { + bool DumpedAny = false; + for (auto *RedeclWithBadType : D->redecls()) { + // FIXME: The redecls() range sometimes has elements of a less-specific + // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives + // us TagDecls, and should give CXXRecordDecls). + auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); + if (!Redecl) { + // Found the injected-class-name for a class template. This will be dumped + // as part of its surrounding class so we don't need to dump it here. + assert(isa<CXXRecordDecl>(RedeclWithBadType) && + "expected an injected-class-name"); + continue; + } + + switch (Redecl->getTemplateSpecializationKind()) { case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDefinition: - if (D == D->getCanonicalDecl()) - dumpDecl(*I); - else - dumpDeclRef(*I); + if (!DumpExplicitInst) + break; + // Fall through. + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + Children.dump(Redecl, DumpRefOnly); + DumpedAny = true; break; case TSK_ExplicitSpecialization: - dumpDeclRef(*I); break; } } + + // Ensure we dump at least one decl for each specialization. + if (!DumpedAny) + Children.dumpRef(D); } -void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { +template<typename TemplateDecl> +void ASTDumper::VisitTemplateDecl(const TemplateDecl *D, + bool DumpExplicitInst) { dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); - ClassTemplateDecl::spec_iterator I = D->spec_begin(); - ClassTemplateDecl::spec_iterator E = D->spec_end(); - if (I == E) - lastChild(); - dumpDecl(D->getTemplatedDecl()); - for (; I != E; ++I) { - ClassTemplateDecl::spec_iterator Next = I; - ++Next; - if (Next == E) - lastChild(); - switch (I->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - if (D == D->getCanonicalDecl()) - dumpDecl(*I); - else - dumpDeclRef(*I); - break; - case TSK_ExplicitSpecialization: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - dumpDeclRef(*I); - break; - } - } + ChildDumper Children(*this); + Children.dump(D->getTemplatedDecl()); + + for (auto *Child : D->specializations()) + VisitTemplateDeclSpecialization(Children, Child, DumpExplicitInst, + !D->isCanonicalDecl()); +} + +void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { + // FIXME: We don't add a declaration of a function template specialization + // to its context when it's explicitly instantiated, so dump explicit + // instantiations when we dump the template itself. + VisitTemplateDecl(D, true); +} + +void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { + VisitTemplateDecl(D, false); } void ASTDumper::VisitClassTemplateSpecializationDecl( @@ -1125,34 +1183,7 @@ void ASTDumper::VisitClassScopeFunctionSpecializationDecl( } void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) { - dumpName(D); - dumpTemplateParameters(D->getTemplateParameters()); - - VarTemplateDecl::spec_iterator I = D->spec_begin(); - VarTemplateDecl::spec_iterator E = D->spec_end(); - if (I == E) - lastChild(); - dumpDecl(D->getTemplatedDecl()); - for (; I != E; ++I) { - VarTemplateDecl::spec_iterator Next = I; - ++Next; - if (Next == E) - lastChild(); - switch (I->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - if (D == D->getCanonicalDecl()) - dumpDecl(*I); - else - dumpDeclRef(*I); - break; - case TSK_ExplicitSpecialization: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - dumpDeclRef(*I); - break; - } - } + VisitTemplateDecl(D, false); } void ASTDumper::VisitVarTemplateSpecializationDecl( @@ -1175,8 +1206,10 @@ void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { if (D->isParameterPack()) OS << " ..."; dumpName(D); - if (D->hasDefaultArgument()) - dumpType(D->getDefaultArgument()); + if (D->hasDefaultArgument()) { + lastChild(); + dumpTemplateArgument(D->getDefaultArgument()); + } } void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { @@ -1184,8 +1217,10 @@ void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { if (D->isParameterPack()) OS << " ..."; dumpName(D); - if (D->hasDefaultArgument()) - dumpStmt(D->getDefaultArgument()); + if (D->hasDefaultArgument()) { + lastChild(); + dumpTemplateArgument(D->getDefaultArgument()); + } } void ASTDumper::VisitTemplateTemplateParmDecl( @@ -1194,8 +1229,10 @@ void ASTDumper::VisitTemplateTemplateParmDecl( OS << " ..."; dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); - if (D->hasDefaultArgument()) + if (D->hasDefaultArgument()) { + lastChild(); dumpTemplateArgumentLoc(D->getDefaultArgument()); + } } void ASTDumper::VisitUsingDecl(const UsingDecl *D) { @@ -1252,8 +1289,6 @@ void ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { dumpType(D->getType()); if (D->getSynthesize()) OS << " synthesize"; - if (D->getBackingIvarReferencedInAccessor()) - OS << " BackingIvarReferencedInAccessor"; switch (D->getAccessControl()) { case ObjCIvarDecl::None: @@ -1280,7 +1315,7 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { else OS << " +"; dumpName(D); - dumpType(D->getResultType()); + dumpType(D->getReturnType()); bool OldMoreChildren = hasMoreChildren(); bool IsVariadic = D->isVariadic(); @@ -1338,28 +1373,20 @@ void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { dumpName(D); - for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), - E = D->protocol_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); - dumpDeclRef(*I); - } + + ChildDumper Children(*this); + for (auto *Child : D->protocols()) + Children.dumpRef(Child); } void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { dumpName(D); dumpDeclRef(D->getSuperClass(), "super"); - if (D->protocol_begin() == D->protocol_end()) - lastChild(); - dumpDeclRef(D->getImplementation()); - for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(), - E = D->protocol_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); - dumpDeclRef(*I); - } + + ChildDumper Children(*this); + Children.dumpRef(D->getImplementation()); + for (auto *Child : D->protocols()) + Children.dumpRef(Child); } void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { @@ -1438,9 +1465,8 @@ void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { } void ASTDumper::VisitBlockDecl(const BlockDecl *D) { - for (BlockDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); - I != E; ++I) - dumpDecl(*I); + for (auto I : D->params()) + dumpDecl(I); if (D->isVariadic()) { IndentScope Indent(*this); @@ -1451,20 +1477,19 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) { IndentScope Indent(*this); OS << "capture this"; } - for (BlockDecl::capture_iterator I = D->capture_begin(), E = D->capture_end(); - I != E; ++I) { + for (const auto &I : D->captures()) { IndentScope Indent(*this); OS << "capture"; - if (I->isByRef()) + if (I.isByRef()) OS << " byref"; - if (I->isNested()) + if (I.isNested()) OS << " nested"; - if (I->getVariable()) { + if (I.getVariable()) { OS << ' '; - dumpBareDeclRef(I->getVariable()); + dumpBareDeclRef(I.getVariable()); } - if (I->hasCopyExpr()) - dumpStmt(I->getCopyExpr()); + if (I.hasCopyExpr()) + dumpStmt(I.getCopyExpr()); } lastChild(); dumpStmt(D->getBody()); @@ -1675,6 +1700,7 @@ void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { case PredefinedExpr::FuncDName: OS << " __FUNCDNAME__"; break; case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break; case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break; + case PredefinedExpr::FuncSig: OS << " __FUNCSIG__"; break; } } @@ -1705,6 +1731,22 @@ void ASTDumper::VisitStringLiteral(const StringLiteral *Str) { Str->outputString(OS); } +void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) { + VisitExpr(ILE); + if (auto *Filler = ILE->getArrayFiller()) { + if (!ILE->getNumInits()) + lastChild(); + IndentScope Indent(*this); + OS << "array filler"; + lastChild(); + dumpStmt(Filler); + } + if (auto *Field = ILE->getInitializedFieldInUnion()) { + OS << " field "; + dumpBareDeclRef(Field); + } +} + void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) { VisitExpr(Node); OS << " " << (Node->isPostfix() ? "postfix" : "prefix") @@ -1849,7 +1891,8 @@ void ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) { void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { VisitExpr(Node); - OS << " selector=" << Node->getSelector().getAsString(); + OS << " selector="; + Node->getSelector().print(OS); switch (Node->getReceiverKind()) { case ObjCMessageExpr::Instance: break; @@ -1871,7 +1914,8 @@ void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { void ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) { VisitExpr(Node); - OS << " selector=" << Node->getBoxingMethod()->getSelector().getAsString(); + OS << " selector="; + Node->getBoxingMethod()->getSelector().print(OS); } void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { @@ -1890,7 +1934,8 @@ void ASTDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) { void ASTDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) { VisitExpr(Node); - OS << " " << Node->getSelector().getAsString(); + OS << " "; + Node->getSelector().print(OS); } void ASTDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) { @@ -1904,13 +1949,13 @@ void ASTDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) { if (Node->isImplicitProperty()) { OS << " Kind=MethodRef Getter=\""; if (Node->getImplicitPropertyGetter()) - OS << Node->getImplicitPropertyGetter()->getSelector().getAsString(); + Node->getImplicitPropertyGetter()->getSelector().print(OS); else OS << "(null)"; OS << "\" Setter=\""; if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter()) - OS << Setter->getSelector().getAsString(); + Setter->getSelector().print(OS); else OS << "(null)"; OS << "\""; @@ -1937,7 +1982,7 @@ void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) { else OS << " Kind=DictionarySubscript GetterForDictionary=\""; if (Node->getAtIndexMethodDecl()) - OS << Node->getAtIndexMethodDecl()->getSelector().getAsString(); + Node->getAtIndexMethodDecl()->getSelector().print(OS); else OS << "(null)"; @@ -1946,7 +1991,7 @@ void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) { else OS << "\" SetterForDictionary=\""; if (Node->setAtIndexMethodDecl()) - OS << Node->setAtIndexMethodDecl()->getSelector().getAsString(); + Node->setAtIndexMethodDecl()->getSelector().print(OS); else OS << "(null)"; } @@ -1975,7 +2020,7 @@ void ASTDumper::dumpFullComment(const FullComment *C) { FC = C; dumpComment(C); - FC = 0; + FC = nullptr; } void ASTDumper::dumpComment(const Comment *C) { @@ -2065,7 +2110,7 @@ void ASTDumper::visitParamCommandComment(const ParamCommandComment *C) { OS << " Param=\"" << C->getParamNameAsWritten() << "\""; } - if (C->isParamIndexValid()) + if (C->isParamIndexValid() && !C->isVarArgParam()) OS << " ParamIndex=" << C->getParamIndex(); } @@ -2106,27 +2151,25 @@ void ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) { // Decl method implementations //===----------------------------------------------------------------------===// -void Decl::dump() const { - dump(llvm::errs()); -} +LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); } -void Decl::dump(raw_ostream &OS) const { +LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS) const { ASTDumper P(OS, &getASTContext().getCommentCommandTraits(), &getASTContext().getSourceManager()); P.dumpDecl(this); } -void Decl::dumpColor() const { +LLVM_DUMP_METHOD void Decl::dumpColor() const { ASTDumper P(llvm::errs(), &getASTContext().getCommentCommandTraits(), &getASTContext().getSourceManager(), /*ShowColors*/true); P.dumpDecl(this); } -void DeclContext::dumpLookups() const { +LLVM_DUMP_METHOD void DeclContext::dumpLookups() const { dumpLookups(llvm::errs()); } -void DeclContext::dumpLookups(raw_ostream &OS) const { +LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS) const { const DeclContext *DC = this; while (!DC->isTranslationUnit()) DC = DC->getParent(); @@ -2139,22 +2182,22 @@ void DeclContext::dumpLookups(raw_ostream &OS) const { // Stmt method implementations //===----------------------------------------------------------------------===// -void Stmt::dump(SourceManager &SM) const { +LLVM_DUMP_METHOD void Stmt::dump(SourceManager &SM) const { dump(llvm::errs(), SM); } -void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { - ASTDumper P(OS, 0, &SM); +LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { + ASTDumper P(OS, nullptr, &SM); P.dumpStmt(this); } -void Stmt::dump() const { - ASTDumper P(llvm::errs(), 0, 0); +LLVM_DUMP_METHOD void Stmt::dump() const { + ASTDumper P(llvm::errs(), nullptr, nullptr); P.dumpStmt(this); } -void Stmt::dumpColor() const { - ASTDumper P(llvm::errs(), 0, 0, /*ShowColors*/true); +LLVM_DUMP_METHOD void Stmt::dumpColor() const { + ASTDumper P(llvm::errs(), nullptr, nullptr, /*ShowColors*/true); P.dumpStmt(this); } @@ -2162,11 +2205,11 @@ void Stmt::dumpColor() const { // Comment method implementations //===----------------------------------------------------------------------===// -void Comment::dump() const { - dump(llvm::errs(), 0, 0); +LLVM_DUMP_METHOD void Comment::dump() const { + dump(llvm::errs(), nullptr, nullptr); } -void Comment::dump(const ASTContext &Context) const { +LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const { dump(llvm::errs(), &Context.getCommentCommandTraits(), &Context.getSourceManager()); } @@ -2178,8 +2221,8 @@ void Comment::dump(raw_ostream &OS, const CommandTraits *Traits, D.dumpFullComment(FC); } -void Comment::dumpColor() const { +LLVM_DUMP_METHOD void Comment::dumpColor() const { const FullComment *FC = dyn_cast<FullComment>(this); - ASTDumper D(llvm::errs(), 0, 0, /*ShowColors*/true); + ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true); D.dumpFullComment(FC); } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index e16015b..b0e0b1d 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -81,7 +81,7 @@ namespace clang { bool ImportDeclParts(NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, SourceLocation &Loc); - void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = 0); + void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr); void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); @@ -407,10 +407,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; + case Type::Adjusted: case Type::Decayed: if (!IsStructurallyEquivalent(Context, - cast<DecayedType>(T1)->getPointeeType(), - cast<DecayedType>(T2)->getPointeeType())) + cast<AdjustedType>(T1)->getOriginalType(), + cast<AdjustedType>(T2)->getOriginalType())) return false; break; @@ -534,12 +535,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::FunctionProto: { const FunctionProtoType *Proto1 = cast<FunctionProtoType>(T1); const FunctionProtoType *Proto2 = cast<FunctionProtoType>(T2); - if (Proto1->getNumArgs() != Proto2->getNumArgs()) + if (Proto1->getNumParams() != Proto2->getNumParams()) return false; - for (unsigned I = 0, N = Proto1->getNumArgs(); I != N; ++I) { - if (!IsStructurallyEquivalent(Context, - Proto1->getArgType(I), - Proto2->getArgType(I))) + for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, Proto1->getParamType(I), + Proto2->getParamType(I))) return false; } if (Proto1->isVariadic() != Proto2->isVariadic()) @@ -570,9 +570,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::FunctionNoProto: { const FunctionType *Function1 = cast<FunctionType>(T1); const FunctionType *Function2 = cast<FunctionType>(T2); - if (!IsStructurallyEquivalent(Context, - Function1->getResultType(), - Function2->getResultType())) + if (!IsStructurallyEquivalent(Context, Function1->getReturnType(), + Function2->getReturnType())) return false; if (Function1->getExtInfo() != Function2->getExtInfo()) return false; @@ -931,10 +930,8 @@ static Optional<unsigned> findAnonymousStructOrUnionIndex(RecordDecl *Anon) { return None; unsigned Index = 0; - for (DeclContext::decl_iterator D = Owner->noload_decls_begin(), - DEnd = Owner->noload_decls_end(); - D != DEnd; ++D) { - FieldDecl *F = dyn_cast<FieldDecl>(*D); + for (const auto *D : Owner->noload_decls()) { + const auto *F = dyn_cast<FieldDecl>(D); if (!F || !F->isAnonymousStructOrUnion()) continue; @@ -1586,7 +1583,7 @@ QualType ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { // FIXME: What happens if we're importing a function without a prototype // into C++? Should we make it variadic? - QualType ToResultType = Importer.Import(T->getResultType()); + QualType ToResultType = Importer.Import(T->getReturnType()); if (ToResultType.isNull()) return QualType(); @@ -1595,16 +1592,14 @@ ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { } QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { - QualType ToResultType = Importer.Import(T->getResultType()); + QualType ToResultType = Importer.Import(T->getReturnType()); if (ToResultType.isNull()) return QualType(); // Import argument types SmallVector<QualType, 4> ArgTypes; - for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), - AEnd = T->arg_type_end(); - A != AEnd; ++A) { - QualType ArgType = Importer.Import(*A); + for (const auto &A : T->param_types()) { + QualType ArgType = Importer.Import(A); if (ArgType.isNull()) return QualType(); ArgTypes.push_back(ArgType); @@ -1612,10 +1607,8 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { // Import exception types SmallVector<QualType, 4> ExceptionTypes; - for (FunctionProtoType::exception_iterator E = T->exception_begin(), - EEnd = T->exception_end(); - E != EEnd; ++E) { - QualType ExceptionType = Importer.Import(*E); + for (const auto &E : T->exceptions()) { + QualType ExceptionType = Importer.Import(E); if (ExceptionType.isNull()) return QualType(); ExceptionTypes.push_back(ExceptionType); @@ -1631,7 +1624,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { ToEPI.RefQualifier = FromEPI.RefQualifier; ToEPI.NumExceptions = ExceptionTypes.size(); ToEPI.Exceptions = ExceptionTypes.data(); - ToEPI.ConsumedArguments = FromEPI.ConsumedArguments; + ToEPI.ConsumedParameters = FromEPI.ConsumedParameters; ToEPI.ExceptionSpecType = FromEPI.ExceptionSpecType; ToEPI.NoexceptExpr = Importer.Import(FromEPI.NoexceptExpr); ToEPI.ExceptionSpecDecl = cast_or_null<FunctionDecl>( @@ -1756,7 +1749,7 @@ QualType ASTNodeImporter::VisitTemplateSpecializationType( } QualType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) { - NestedNameSpecifier *ToQualifier = 0; + NestedNameSpecifier *ToQualifier = nullptr; // Note: the qualifier in an ElaboratedType is optional. if (T->getQualifier()) { ToQualifier = Importer.Import(T->getQualifier()); @@ -1787,11 +1780,9 @@ QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) { return QualType(); SmallVector<ObjCProtocolDecl *, 4> Protocols; - for (ObjCObjectType::qual_iterator P = T->qual_begin(), - PEnd = T->qual_end(); - P != PEnd; ++P) { + for (auto *P : T->quals()) { ObjCProtocolDecl *Protocol - = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(*P)); + = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(P)); if (!Protocol) return QualType(); Protocols.push_back(Protocol); @@ -1909,11 +1900,8 @@ void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { return; } - for (DeclContext::decl_iterator From = FromDC->decls_begin(), - FromEnd = FromDC->decls_end(); - From != FromEnd; - ++From) - Importer.Import(*From); + for (auto *From : FromDC->decls()) + Importer.Import(From); } bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, @@ -1946,6 +1934,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.HasProtectedFields = FromData.HasProtectedFields; ToData.HasPublicFields = FromData.HasPublicFields; ToData.HasMutableFields = FromData.HasMutableFields; + ToData.HasVariantMembers = FromData.HasVariantMembers; ToData.HasOnlyCMembers = FromData.HasOnlyCMembers; ToData.HasInClassInitializer = FromData.HasInClassInitializer; ToData.HasUninitializedReferenceMember @@ -1986,29 +1975,25 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.IsLambda = FromData.IsLambda; SmallVector<CXXBaseSpecifier *, 4> Bases; - for (CXXRecordDecl::base_class_iterator - Base1 = FromCXX->bases_begin(), - FromBaseEnd = FromCXX->bases_end(); - Base1 != FromBaseEnd; - ++Base1) { - QualType T = Importer.Import(Base1->getType()); + for (const auto &Base1 : FromCXX->bases()) { + QualType T = Importer.Import(Base1.getType()); if (T.isNull()) return true; SourceLocation EllipsisLoc; - if (Base1->isPackExpansion()) - EllipsisLoc = Importer.Import(Base1->getEllipsisLoc()); + if (Base1.isPackExpansion()) + EllipsisLoc = Importer.Import(Base1.getEllipsisLoc()); // Ensure that we have a definition for the base. - ImportDefinitionIfNeeded(Base1->getType()->getAsCXXRecordDecl()); + ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl()); Bases.push_back( new (Importer.getToContext()) - CXXBaseSpecifier(Importer.Import(Base1->getSourceRange()), - Base1->isVirtual(), - Base1->isBaseOfClass(), - Base1->getAccessSpecifierAsWritten(), - Importer.Import(Base1->getTypeSourceInfo()), + CXXBaseSpecifier(Importer.Import(Base1.getSourceRange()), + Base1.isVirtual(), + Base1.isBaseOfClass(), + Base1.getAccessSpecifierAsWritten(), + Importer.Import(Base1.getTypeSourceInfo()), EllipsisLoc)); } if (!Bases.empty()) @@ -2075,8 +2060,8 @@ TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList( P != PEnd; ++P) { Decl *To = Importer.Import(*P); if (!To) - return 0; - + return nullptr; + ToParams.push_back(cast<NamedDecl>(To)); } @@ -2236,7 +2221,7 @@ bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, Decl *ASTNodeImporter::VisitDecl(Decl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return 0; + return nullptr; } Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { @@ -2254,9 +2239,9 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - - NamespaceDecl *MergeWithNamespace = 0; + return nullptr; + + NamespaceDecl *MergeWithNamespace = nullptr; if (!Name) { // This is an anonymous namespace. Adopt an existing anonymous // namespace if we can. @@ -2296,7 +2281,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { D->isInline(), Importer.Import(D->getLocStart()), Loc, Name.getAsIdentifierInfo(), - /*PrevDecl=*/0); + /*PrevDecl=*/nullptr); ToNamespace->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToNamespace); @@ -2322,8 +2307,8 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // If this typedef is not in block scope, determine whether we've // seen a typedef with the same name (that we can merge with) or any // other entity by that name (which name lookup could conflict with). @@ -2350,15 +2335,15 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return 0; + return nullptr; } } // Import the underlying type of this typedef; QualType T = Importer.Import(D->getUnderlyingType()); if (T.isNull()) - return 0; - + return nullptr; + // Create the new typedef node. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); SourceLocation StartL = Importer.Import(D->getLocStart()); @@ -2396,8 +2381,8 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // Figure out what enum name we're looking for. unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; @@ -2440,7 +2425,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Create the enum declaration. EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getLocStart()), - Loc, Name.getAsIdentifierInfo(), 0, + Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); // Import the qualifier, if any. @@ -2453,12 +2438,12 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Import the integer type. QualType ToIntegerType = Importer.Import(D->getIntegerType()); if (ToIntegerType.isNull()) - return 0; + return nullptr; D2->setIntegerType(ToIntegerType); // Import the definition if (D->isCompleteDefinition() && ImportDefinition(D, D2)) - return 0; + return nullptr; return D2; } @@ -2471,8 +2456,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (Definition && Definition != D) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) - return 0; - + return nullptr; + return Importer.Imported(D, ImportedDef); } @@ -2481,8 +2466,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // Figure out what structure name we're looking for. unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; @@ -2493,7 +2478,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { IDNS |= Decl::IDNS_Ordinary; // We may already have a record of the same name; try to find and match it. - RecordDecl *AdoptDecl = 0; + RecordDecl *AdoptDecl = nullptr; if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; @@ -2538,6 +2523,21 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } else if (!D->isCompleteDefinition()) { // We have a forward declaration of this type, so adopt that forward // declaration rather than building a new one. + + // If one or both can be completed from external storage then try one + // last time to complete and compare them before doing this. + + if (FoundRecord->hasExternalLexicalStorage() && + !FoundRecord->isCompleteDefinition()) + FoundRecord->getASTContext().getExternalSource()->CompleteType(FoundRecord); + if (D->hasExternalLexicalStorage()) + D->getASTContext().getExternalSource()->CompleteType(D); + + if (FoundRecord->isCompleteDefinition() && + D->isCompleteDefinition() && + !IsStructuralMatch(D, FoundRecord)) + continue; + AdoptDecl = FoundRecord; continue; } else if (!SearchName) { @@ -2581,8 +2581,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Importer.Imported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default)) - return 0; - + return nullptr; + return D2; } @@ -2592,11 +2592,11 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; + return nullptr; // Determine whether there are any other declarations with the same name and // in the same context. @@ -2623,14 +2623,14 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return 0; + return nullptr; } } Expr *Init = Importer.Import(D->getInitExpr()); if (D->getInitExpr() && !Init) - return 0; - + return nullptr; + EnumConstantDecl *ToEnumerator = EnumConstantDecl::Create(Importer.getToContext(), cast<EnumDecl>(DC), Loc, Name.getAsIdentifierInfo(), T, @@ -2648,7 +2648,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. @@ -2694,7 +2694,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return 0; + return nullptr; } } @@ -2716,7 +2716,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { FromEPI.NoexceptExpr) { FunctionProtoType::ExtProtoInfo DefaultEPI; FromTy = Importer.getFromContext().getFunctionType( - FromFPT->getResultType(), FromFPT->getArgTypes(), DefaultEPI); + FromFPT->getReturnType(), FromFPT->getParamTypes(), DefaultEPI); usedDifferentExceptionSpec = true; } } @@ -2724,22 +2724,21 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Import the type. QualType T = Importer.Import(FromTy); if (T.isNull()) - return 0; - + return nullptr; + // Import the function parameters. SmallVector<ParmVarDecl *, 8> Parameters; - for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); - P != PEnd; ++P) { - ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(*P)); + for (auto P : D->params()) { + ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P)); if (!ToP) - return 0; - + return nullptr; + Parameters.push_back(ToP); } // Create the imported function. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - FunctionDecl *ToFunction = 0; + FunctionDecl *ToFunction = nullptr; if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { ToFunction = CXXConstructorDecl::Create(Importer.getToContext(), cast<CXXRecordDecl>(DC), @@ -2804,7 +2803,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Update FunctionProtoType::ExtProtoInfo. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; + return nullptr; ToFunction->setType(T); } @@ -2838,10 +2837,8 @@ static unsigned getFieldIndex(Decl *F) { return 0; unsigned Index = 1; - for (DeclContext::decl_iterator D = Owner->noload_decls_begin(), - DEnd = Owner->noload_decls_end(); - D != DEnd; ++D) { - if (*D == F) + for (const auto *D : Owner->noload_decls()) { + if (D == F) return Index; if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) @@ -2857,8 +2854,8 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // Determine whether we've already imported this field. SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); @@ -2878,20 +2875,20 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return 0; + return nullptr; } } // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); Expr *BitWidth = Importer.Import(D->getBitWidth()); if (!BitWidth && D->getBitWidth()) - return 0; - + return nullptr; + FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), @@ -2913,7 +2910,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; // Determine whether we've already imported this field. SmallVector<NamedDecl *, 2> FoundDecls; @@ -2940,24 +2937,23 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return 0; + return nullptr; } } // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; + return nullptr; NamedDecl **NamedChain = new (Importer.getToContext())NamedDecl*[D->getChainingSize()]; unsigned i = 0; - for (IndirectFieldDecl::chain_iterator PI = D->chain_begin(), - PE = D->chain_end(); PI != PE; ++PI) { - Decl* D = Importer.Import(*PI); + for (auto *PI : D->chain()) { + Decl *D = Importer.Import(PI); if (!D) - return 0; + return nullptr; NamedChain[i++] = cast<NamedDecl>(D); } @@ -2978,8 +2974,8 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // Determine whether we've already imported this ivar SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); @@ -2995,27 +2991,26 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { << Name << D->getType() << FoundIvar->getType(); Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here) << FoundIvar->getType(); - return 0; + return nullptr; } } // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); Expr *BitWidth = Importer.Import(D->getBitWidth()); if (!BitWidth && D->getBitWidth()) - return 0; - + return nullptr; + ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), cast<ObjCContainerDecl>(DC), Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), - BitWidth, D->getSynthesize(), - D->getBackingIvarReferencedInAccessor()); + BitWidth, D->getSynthesize()); ToIvar->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToIvar); LexicalDC->addDeclInternal(ToIvar); @@ -3029,12 +3024,12 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // Try to find a variable in our own ("to") context with the same name and // in the same context as the variable we're importing. if (D->isFileVarDecl()) { - VarDecl *MergeWithVar = 0; + VarDecl *MergeWithVar = nullptr; SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; @@ -3063,8 +3058,8 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + FoundVar->setType(T); MergeWithVar = FoundVar; break; @@ -3115,15 +3110,15 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return 0; + return nullptr; } } // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + // Create the imported variable. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, @@ -3139,7 +3134,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { // Merge the initializer. if (ImportDefinition(D, ToVar)) - return 0; + return nullptr; return ToVar; } @@ -3152,16 +3147,16 @@ Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { // Import the name of this declaration. DeclarationName Name = Importer.Import(D->getDeclName()); if (D->getDeclName() && !Name) - return 0; - + return nullptr; + // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); // Import the parameter's type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + // Create the imported parameter. ImplicitParamDecl *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, @@ -3178,23 +3173,23 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { // Import the name of this declaration. DeclarationName Name = Importer.Import(D->getDeclName()); if (D->getDeclName() && !Name) - return 0; - + return nullptr; + // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); // Import the parameter's type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + // Create the imported parameter. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); ParmVarDecl *ToParm = ParmVarDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(), - /*FIXME: Default argument*/ 0); + /*FIXME: Default argument*/nullptr); ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); return Importer.Imported(D, ToParm); } @@ -3205,8 +3200,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { @@ -3215,15 +3210,15 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { continue; // Check return types. - if (!Importer.IsStructurallyEquivalent(D->getResultType(), - FoundMethod->getResultType())) { + if (!Importer.IsStructurallyEquivalent(D->getReturnType(), + FoundMethod->getReturnType())) { Importer.ToDiag(Loc, diag::err_odr_objc_method_result_type_inconsistent) - << D->isInstanceMethod() << Name - << D->getResultType() << FoundMethod->getResultType(); + << D->isInstanceMethod() << Name << D->getReturnType() + << FoundMethod->getReturnType(); Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return 0; + return nullptr; } // Check the number of parameters. @@ -3234,7 +3229,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return 0; + return nullptr; } // Check parameter types. @@ -3249,7 +3244,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { << (*P)->getType() << (*FoundP)->getType(); Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here) << (*FoundP)->getType(); - return 0; + return nullptr; } } @@ -3261,7 +3256,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return 0; + return nullptr; } // FIXME: Any other bits we need to merge? @@ -3270,39 +3265,28 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { } // Import the result type. - QualType ResultTy = Importer.Import(D->getResultType()); + QualType ResultTy = Importer.Import(D->getReturnType()); if (ResultTy.isNull()) - return 0; + return nullptr; + + TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo()); - TypeSourceInfo *ResultTInfo = Importer.Import(D->getResultTypeSourceInfo()); - - ObjCMethodDecl *ToMethod - = ObjCMethodDecl::Create(Importer.getToContext(), - Loc, - Importer.Import(D->getLocEnd()), - Name.getObjCSelector(), - ResultTy, ResultTInfo, DC, - D->isInstanceMethod(), - D->isVariadic(), - D->isPropertyAccessor(), - D->isImplicit(), - D->isDefined(), - D->getImplementationControl(), - D->hasRelatedResultType()); + ObjCMethodDecl *ToMethod = ObjCMethodDecl::Create( + Importer.getToContext(), Loc, Importer.Import(D->getLocEnd()), + Name.getObjCSelector(), ResultTy, ReturnTInfo, DC, D->isInstanceMethod(), + D->isVariadic(), D->isPropertyAccessor(), D->isImplicit(), D->isDefined(), + D->getImplementationControl(), D->hasRelatedResultType()); // FIXME: When we decide to merge method definitions, we'll need to // deal with implicit parameters. // Import the parameters SmallVector<ParmVarDecl *, 5> ToParams; - for (ObjCMethodDecl::param_iterator FromP = D->param_begin(), - FromPEnd = D->param_end(); - FromP != FromPEnd; - ++FromP) { - ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(*FromP)); + for (auto *FromP : D->params()) { + ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP)); if (!ToP) - return 0; - + return nullptr; + ToParams.push_back(ToP); } @@ -3327,13 +3311,13 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + ObjCInterfaceDecl *ToInterface = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface())); if (!ToInterface) - return 0; - + return nullptr; + // Determine if we've already encountered this category. ObjCCategoryDecl *MergeWithCategory = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo()); @@ -3363,7 +3347,7 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { ObjCProtocolDecl *ToProto = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); if (!ToProto) - return 0; + return nullptr; Protocols.push_back(ToProto); ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); } @@ -3385,8 +3369,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { = cast_or_null<ObjCCategoryImplDecl>( Importer.Import(D->getImplementation())); if (!Impl) - return 0; - + return nullptr; + ToCategory->setImplementation(Impl); } @@ -3441,8 +3425,8 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { if (Definition && Definition != D) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) - return 0; - + return nullptr; + return Importer.Imported(D, ImportedDef); } @@ -3451,9 +3435,9 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; - ObjCProtocolDecl *MergeWithProtocol = 0; + ObjCProtocolDecl *MergeWithProtocol = nullptr; SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { @@ -3469,7 +3453,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, Name.getAsIdentifierInfo(), Loc, Importer.Import(D->getAtStartLoc()), - /*PrevDecl=*/0); + /*PrevDecl=*/nullptr); ToProto->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProto); } @@ -3477,8 +3461,8 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { Importer.Imported(D, ToProto); if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto)) - return 0; - + return nullptr; + return ToProto; } @@ -3558,12 +3542,8 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, // Import categories. When the categories themselves are imported, they'll // hook themselves into this interface. - for (ObjCInterfaceDecl::known_categories_iterator - Cat = From->known_categories_begin(), - CatEnd = From->known_categories_end(); - Cat != CatEnd; ++Cat) { - Importer.Import(*Cat); - } + for (auto *Cat : From->known_categories()) + Importer.Import(Cat); // If we have an @implementation, import it as well. if (From->getImplementation()) { @@ -3590,8 +3570,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { if (Definition && Definition != D) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) - return 0; - + return nullptr; + return Importer.Imported(D, ImportedDef); } @@ -3600,10 +3580,10 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; // Look for an existing interface with the same name. - ObjCInterfaceDecl *MergeWithIface = 0; + ObjCInterfaceDecl *MergeWithIface = nullptr; SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { @@ -3620,7 +3600,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(), - /*PrevDecl=*/0,Loc, + /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl()); ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIface); @@ -3628,8 +3608,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { Importer.Imported(D, ToIface); if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface)) - return 0; - + return nullptr; + return ToIface; } @@ -3637,14 +3617,14 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { ObjCCategoryDecl *Category = cast_or_null<ObjCCategoryDecl>( Importer.Import(D->getCategoryDecl())); if (!Category) - return 0; - + return nullptr; + ObjCCategoryImplDecl *ToImpl = Category->getImplementation(); if (!ToImpl) { DeclContext *DC = Importer.ImportContext(D->getDeclContext()); if (!DC) - return 0; - + return nullptr; + SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc()); ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getIdentifier()), @@ -3657,8 +3637,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); if (!LexicalDC) - return 0; - + return nullptr; + ToImpl->setLexicalDeclContext(LexicalDC); } @@ -3676,15 +3656,15 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { ObjCInterfaceDecl *Iface = cast_or_null<ObjCInterfaceDecl>( Importer.Import(D->getClassInterface())); if (!Iface) - return 0; + return nullptr; // Import the superclass, if any. - ObjCInterfaceDecl *Super = 0; + ObjCInterfaceDecl *Super = nullptr; if (D->getSuperClass()) { Super = cast_or_null<ObjCInterfaceDecl>( Importer.Import(D->getSuperClass())); if (!Super) - return 0; + return nullptr; } ObjCImplementationDecl *Impl = Iface->getImplementation(); @@ -3704,7 +3684,7 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); if (!LexicalDC) - return 0; + return nullptr; Impl->setLexicalDeclContext(LexicalDC); } @@ -3717,28 +3697,29 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { // Verify that the existing @implementation has the same superclass. if ((Super && !Impl->getSuperClass()) || (!Super && Impl->getSuperClass()) || - (Super && Impl->getSuperClass() && - !declaresSameEntity(Super->getCanonicalDecl(), Impl->getSuperClass()))) { - Importer.ToDiag(Impl->getLocation(), - diag::err_odr_objc_superclass_inconsistent) - << Iface->getDeclName(); - // FIXME: It would be nice to have the location of the superclass - // below. - if (Impl->getSuperClass()) - Importer.ToDiag(Impl->getLocation(), + (Super && Impl->getSuperClass() && + !declaresSameEntity(Super->getCanonicalDecl(), + Impl->getSuperClass()))) { + Importer.ToDiag(Impl->getLocation(), + diag::err_odr_objc_superclass_inconsistent) + << Iface->getDeclName(); + // FIXME: It would be nice to have the location of the superclass + // below. + if (Impl->getSuperClass()) + Importer.ToDiag(Impl->getLocation(), + diag::note_odr_objc_superclass) + << Impl->getSuperClass()->getDeclName(); + else + Importer.ToDiag(Impl->getLocation(), + diag::note_odr_objc_missing_superclass); + if (D->getSuperClass()) + Importer.FromDiag(D->getLocation(), diag::note_odr_objc_superclass) - << Impl->getSuperClass()->getDeclName(); - else - Importer.ToDiag(Impl->getLocation(), + << D->getSuperClass()->getDeclName(); + else + Importer.FromDiag(D->getLocation(), diag::note_odr_objc_missing_superclass); - if (D->getSuperClass()) - Importer.FromDiag(D->getLocation(), - diag::note_odr_objc_superclass) - << D->getSuperClass()->getDeclName(); - else - Importer.FromDiag(D->getLocation(), - diag::note_odr_objc_missing_superclass); - return 0; + return nullptr; } } @@ -3754,7 +3735,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; // Check whether we have already imported this property. SmallVector<NamedDecl *, 2> FoundDecls; @@ -3769,7 +3750,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { << Name << D->getType() << FoundProp->getType(); Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here) << FoundProp->getType(); - return 0; + return nullptr; } // FIXME: Check property attributes, getters, setters, etc.? @@ -3783,7 +3764,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { // Import the type. TypeSourceInfo *T = Importer.Import(D->getTypeSourceInfo()); if (!T) - return 0; + return nullptr; // Create the new property. ObjCPropertyDecl *ToProperty @@ -3815,31 +3796,31 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { ObjCPropertyDecl *Property = cast_or_null<ObjCPropertyDecl>( Importer.Import(D->getPropertyDecl())); if (!Property) - return 0; + return nullptr; DeclContext *DC = Importer.ImportContext(D->getDeclContext()); if (!DC) - return 0; - + return nullptr; + // Import the lexical declaration context. DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); if (!LexicalDC) - return 0; + return nullptr; } ObjCImplDecl *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC); if (!InImpl) - return 0; + return nullptr; // Import the ivar (for an @synthesize). - ObjCIvarDecl *Ivar = 0; + ObjCIvarDecl *Ivar = nullptr; if (D->getPropertyIvarDecl()) { Ivar = cast_or_null<ObjCIvarDecl>( Importer.Import(D->getPropertyIvarDecl())); if (!Ivar) - return 0; + return nullptr; } ObjCPropertyImplDecl *ToImpl @@ -3868,7 +3849,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { diag::note_odr_objc_property_impl_kind) << D->getPropertyDecl()->getDeclName() << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); - return 0; + return nullptr; } // For @synthesize, check that we have the same @@ -3882,7 +3863,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { Importer.FromDiag(D->getPropertyIvarDeclLoc(), diag::note_odr_objc_synthesize_ivar_here) << D->getPropertyIvarDecl()->getDeclName(); - return 0; + return nullptr; } // Merge the existing implementation with the new implementation. @@ -3914,21 +3895,21 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { // Import the name of this declaration. DeclarationName Name = Importer.Import(D->getDeclName()); if (D->getDeclName() && !Name) - return 0; - + return nullptr; + // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); // Import the type of this declaration. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + // Import type-source information. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); if (D->getTypeSourceInfo() && !TInfo) - return 0; - + return nullptr; + // FIXME: Import default argument. return NonTypeTemplateParmDecl::Create(Importer.getToContext(), @@ -3944,8 +3925,8 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { // Import the name of this declaration. DeclarationName Name = Importer.Import(D->getDeclName()); if (D->getDeclName() && !Name) - return 0; - + return nullptr; + // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); @@ -3953,8 +3934,8 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); if (!TemplateParams) - return 0; - + return nullptr; + // FIXME: Import default argument. return TemplateTemplateParmDecl::Create(Importer.getToContext(), @@ -3975,8 +3956,8 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { Decl *ImportedDef = Importer.Import(Definition->getDescribedClassTemplate()); if (!ImportedDef) - return 0; - + return nullptr; + return Importer.Imported(D, ImportedDef); } @@ -3985,8 +3966,8 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // We may already have a template of the same name; try to find and match it. if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; @@ -4019,7 +4000,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { } if (!Name) - return 0; + return nullptr; } CXXRecordDecl *DTemplated = D->getTemplatedDecl(); @@ -4039,12 +4020,12 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); if (!TemplateParams) - return 0; - + return nullptr; + ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated, - /*PrevDecl=*/0); + /*PrevDecl=*/nullptr); D2Templated->setDescribedClassTemplate(D2); D2->setAccess(D->getAccess()); @@ -4072,8 +4053,8 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (Definition && Definition != D) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) - return 0; - + return nullptr; + return Importer.Imported(D, ImportedDef); } @@ -4081,18 +4062,18 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( = cast_or_null<ClassTemplateDecl>(Importer.Import( D->getSpecializedTemplate())); if (!ClassTemplate) - return 0; - + return nullptr; + // Import the context of this declaration. DeclContext *DC = ClassTemplate->getDeclContext(); if (!DC) - return 0; - + return nullptr; + DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); if (!LexicalDC) - return 0; + return nullptr; } // Import the location of this declaration. @@ -4104,13 +4085,12 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (ImportTemplateArguments(D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) - return 0; - + return nullptr; + // Try to find an existing specialization with these template arguments. - void *InsertPos = 0; + void *InsertPos = nullptr; ClassTemplateSpecializationDecl *D2 - = ClassTemplate->findSpecialization(TemplateArgs.data(), - TemplateArgs.size(), InsertPos); + = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); if (D2) { // We already have a class template specialization with these template // arguments. @@ -4133,7 +4113,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( ClassTemplate, TemplateArgs.data(), TemplateArgs.size(), - /*PrevDecl=*/0); + /*PrevDecl=*/nullptr); D2->setSpecializationKind(D->getSpecializationKind()); // Add this specialization to the class template. @@ -4149,8 +4129,8 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( Importer.Imported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2)) - return 0; - + return nullptr; + return D2; } @@ -4164,7 +4144,7 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { if (Definition && Definition != D->getTemplatedDecl()) { Decl *ImportedDef = Importer.Import(Definition->getDescribedVarTemplate()); if (!ImportedDef) - return 0; + return nullptr; return Importer.Imported(D, ImportedDef); } @@ -4174,7 +4154,7 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; // We may already have a template of the same name; try to find and match it. assert(!DC->isFunctionOrMethod() && @@ -4206,14 +4186,14 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { } if (!Name) - return 0; + return nullptr; VarDecl *DTemplated = D->getTemplatedDecl(); // Import the type. QualType T = Importer.Import(DTemplated->getType()); if (T.isNull()) - return 0; + return nullptr; // Create the declaration that is being templated. SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart()); @@ -4231,17 +4211,16 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { // Merge the initializer. if (ImportDefinition(DTemplated, D2Templated)) - return 0; + return nullptr; // Create the variable template declaration itself. TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); if (!TemplateParams) - return 0; + return nullptr; VarTemplateDecl *D2 = VarTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated, - /*PrevDecl=*/0); + Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated); D2Templated->setDescribedVarTemplate(D2); D2->setAccess(D->getAccess()); @@ -4269,7 +4248,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( if (Definition && Definition != D) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) - return 0; + return nullptr; return Importer.Imported(D, ImportedDef); } @@ -4277,18 +4256,18 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( VarTemplateDecl *VarTemplate = cast_or_null<VarTemplateDecl>( Importer.Import(D->getSpecializedTemplate())); if (!VarTemplate) - return 0; + return nullptr; // Import the context of this declaration. DeclContext *DC = VarTemplate->getDeclContext(); if (!DC) - return 0; + return nullptr; DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); if (!LexicalDC) - return 0; + return nullptr; } // Import the location of this declaration. @@ -4299,12 +4278,12 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( SmallVector<TemplateArgument, 2> TemplateArgs; if (ImportTemplateArguments(D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) - return 0; + return nullptr; // Try to find an existing specialization with these template arguments. - void *InsertPos = 0; + void *InsertPos = nullptr; VarTemplateSpecializationDecl *D2 = VarTemplate->findSpecialization( - TemplateArgs.data(), TemplateArgs.size(), InsertPos); + TemplateArgs, InsertPos); if (D2) { // We already have a variable template specialization with these template // arguments. @@ -4325,7 +4304,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; + return nullptr; TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); // Create a new specialization. @@ -4348,7 +4327,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( Importer.Imported(D, D2); if (D->isThisDeclarationADefinition() && ImportDefinition(D, D2)) - return 0; + return nullptr; return D2; } @@ -4360,7 +4339,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( Stmt *ASTNodeImporter::VisitStmt(Stmt *S) { Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node) << S->getStmtClassName(); - return 0; + return nullptr; } //---------------------------------------------------------------------------- @@ -4369,24 +4348,24 @@ Stmt *ASTNodeImporter::VisitStmt(Stmt *S) { Expr *ASTNodeImporter::VisitExpr(Expr *E) { Importer.FromDiag(E->getLocStart(), diag::err_unsupported_ast_node) << E->getStmtClassName(); - return 0; + return nullptr; } Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl())); if (!ToD) - return 0; + return nullptr; - NamedDecl *FoundD = 0; + NamedDecl *FoundD = nullptr; if (E->getDecl() != E->getFoundDecl()) { FoundD = cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl())); if (!FoundD) - return 0; + return nullptr; } QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; + return nullptr; DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(), Importer.Import(E->getQualifierLoc()), @@ -4396,7 +4375,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { Importer.Import(E->getLocation()), T, E->getValueKind(), FoundD, - /*FIXME:TemplateArgs=*/0); + /*FIXME:TemplateArgs=*/nullptr); if (E->hadMultipleCandidates()) DRE->setHadMultipleCandidates(true); return DRE; @@ -4405,7 +4384,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; + return nullptr; return IntegerLiteral::Create(Importer.getToContext(), E->getValue(), T, @@ -4415,8 +4394,8 @@ Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; - + return nullptr; + return new (Importer.getToContext()) CharacterLiteral(E->getValue(), E->getKind(), T, Importer.Import(E->getLocation())); @@ -4425,8 +4404,8 @@ Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Expr *SubExpr = Importer.Import(E->getSubExpr()); if (!SubExpr) - return 0; - + return nullptr; + return new (Importer.getToContext()) ParenExpr(Importer.Import(E->getLParen()), Importer.Import(E->getRParen()), @@ -4436,12 +4415,12 @@ Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; + return nullptr; Expr *SubExpr = Importer.Import(E->getSubExpr()); if (!SubExpr) - return 0; - + return nullptr; + return new (Importer.getToContext()) UnaryOperator(SubExpr, E->getOpcode(), T, E->getValueKind(), E->getObjectKind(), @@ -4455,8 +4434,8 @@ Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr( if (E->isArgumentType()) { TypeSourceInfo *TInfo = Importer.Import(E->getArgumentTypeInfo()); if (!TInfo) - return 0; - + return nullptr; + return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(), TInfo, ResultType, Importer.Import(E->getOperatorLoc()), @@ -4465,8 +4444,8 @@ Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr( Expr *SubExpr = Importer.Import(E->getArgumentExpr()); if (!SubExpr) - return 0; - + return nullptr; + return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(), SubExpr, ResultType, Importer.Import(E->getOperatorLoc()), @@ -4476,16 +4455,16 @@ Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr( Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; + return nullptr; Expr *LHS = Importer.Import(E->getLHS()); if (!LHS) - return 0; - + return nullptr; + Expr *RHS = Importer.Import(E->getRHS()); if (!RHS) - return 0; - + return nullptr; + return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(), T, E->getValueKind(), E->getObjectKind(), @@ -4496,24 +4475,24 @@ Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; - + return nullptr; + QualType CompLHSType = Importer.Import(E->getComputationLHSType()); if (CompLHSType.isNull()) - return 0; - + return nullptr; + QualType CompResultType = Importer.Import(E->getComputationResultType()); if (CompResultType.isNull()) - return 0; - + return nullptr; + Expr *LHS = Importer.Import(E->getLHS()); if (!LHS) - return 0; - + return nullptr; + Expr *RHS = Importer.Import(E->getRHS()); if (!RHS) - return 0; - + return nullptr; + return new (Importer.getToContext()) CompoundAssignOperator(LHS, RHS, E->getOpcode(), T, E->getValueKind(), @@ -4533,15 +4512,15 @@ static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) { Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; + return nullptr; Expr *SubExpr = Importer.Import(E->getSubExpr()); if (!SubExpr) - return 0; + return nullptr; CXXCastPath BasePath; if (ImportCastPath(E, BasePath)) - return 0; + return nullptr; return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(), SubExpr, &BasePath, E->getValueKind()); @@ -4550,19 +4529,19 @@ Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; - + return nullptr; + Expr *SubExpr = Importer.Import(E->getSubExpr()); if (!SubExpr) - return 0; + return nullptr; TypeSourceInfo *TInfo = Importer.Import(E->getTypeInfoAsWritten()); if (!TInfo && E->getTypeInfoAsWritten()) - return 0; - + return nullptr; + CXXCastPath BasePath; if (ImportCastPath(E, BasePath)) - return 0; + return nullptr; return CStyleCastExpr::Create(Importer.getToContext(), T, E->getValueKind(), E->getCastKind(), @@ -4616,7 +4595,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { // on the type and a single location. Implement a real version of this. QualType T = Import(FromTSI->getType()); if (T.isNull()) - return 0; + return nullptr; return ToContext.getTrivialTypeSourceInfo(T, FromTSI->getTypeLoc().getLocStart()); @@ -4624,7 +4603,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { Decl *ASTImporter::Import(Decl *FromD) { if (!FromD) - return 0; + return nullptr; ASTNodeImporter Importer(*this); @@ -4639,8 +4618,8 @@ Decl *ASTImporter::Import(Decl *FromD) { // Import the type Decl *ToD = Importer.Visit(FromD); if (!ToD) - return 0; - + return nullptr; + // Record the imported declaration. ImportedDecls[FromD] = ToD; @@ -4675,8 +4654,8 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { DeclContext *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC))); if (!ToDC) - return 0; - + return nullptr; + // When we're using a record/enum/Objective-C class/protocol as a context, we // need it to have a definition. if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(ToDC)) { @@ -4726,14 +4705,14 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { Expr *ASTImporter::Import(Expr *FromE) { if (!FromE) - return 0; + return nullptr; return cast_or_null<Expr>(Import(cast<Stmt>(FromE))); } Stmt *ASTImporter::Import(Stmt *FromS) { if (!FromS) - return 0; + return nullptr; // Check whether we've already imported this declaration. llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS); @@ -4744,8 +4723,8 @@ Stmt *ASTImporter::Import(Stmt *FromS) { ASTNodeImporter Importer(*this); Stmt *ToS = Importer.Visit(FromS); if (!ToS) - return 0; - + return nullptr; + // Record the imported declaration. ImportedStmts[FromS] = ToS; return ToS; @@ -4753,7 +4732,7 @@ Stmt *ASTImporter::Import(Stmt *FromS) { NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { if (!FromNNS) - return 0; + return nullptr; NestedNameSpecifier *prefix = Import(FromNNS->getPrefix()); @@ -4762,21 +4741,21 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { if (IdentifierInfo *II = Import(FromNNS->getAsIdentifier())) { return NestedNameSpecifier::Create(ToContext, prefix, II); } - return 0; + return nullptr; case NestedNameSpecifier::Namespace: if (NamespaceDecl *NS = cast<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) { return NestedNameSpecifier::Create(ToContext, prefix, NS); } - return 0; + return nullptr; case NestedNameSpecifier::NamespaceAlias: if (NamespaceAliasDecl *NSAD = cast<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) { return NestedNameSpecifier::Create(ToContext, prefix, NSAD); } - return 0; + return nullptr; case NestedNameSpecifier::Global: return NestedNameSpecifier::GlobalSpecifier(ToContext); @@ -4791,7 +4770,7 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { bTemplate, T.getTypePtr()); } } - return 0; + return nullptr; } llvm_unreachable("Invalid nested name specifier kind"); @@ -4943,8 +4922,7 @@ FileID ASTImporter::Import(FileID FromID) { llvm::MemoryBuffer *ToBuf = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), FromBuf->getBufferIdentifier()); - ToID = ToSM.createFileIDForMemBuffer(ToBuf, - FromSLoc.getFile().getFileCharacteristic()); + ToID = ToSM.createFileID(ToBuf, FromSLoc.getFile().getFileCharacteristic()); } @@ -5054,7 +5032,7 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) { IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { if (!FromId) - return 0; + return nullptr; return &ToContext.Idents.get(FromId->getName()); } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp b/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp index ae47ea9..baa8e48 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp @@ -39,18 +39,24 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { #include "clang/AST/TypeNodes.def" }; -bool ASTNodeKind::isBaseOf(ASTNodeKind Other) const { - return isBaseOf(KindId, Other.KindId); +bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { + return isBaseOf(KindId, Other.KindId, Distance); } bool ASTNodeKind::isSame(ASTNodeKind Other) const { return KindId != NKI_None && KindId == Other.KindId; } -bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived) { +bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived, + unsigned *Distance) { if (Base == NKI_None || Derived == NKI_None) return false; - while (Derived != Base && Derived != NKI_None) + unsigned Dist = 0; + while (Derived != Base && Derived != NKI_None) { Derived = AllKindInfo[Derived].ParentId; + ++Dist; + } + if (Distance) + *Distance = Dist; return Derived == Base; } @@ -71,7 +77,7 @@ void DynTypedNode::print(llvm::raw_ostream &OS, else if (const Decl *D = get<Decl>()) D->print(OS, PP); else if (const Stmt *S = get<Stmt>()) - S->printPretty(OS, 0, PP); + S->printPretty(OS, nullptr, PP); else if (const Type *T = get<Type>()) QualType(T, 0).print(OS, PP); else diff --git a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp index 7af3c8b..0bf6bcd 100644 --- a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp @@ -24,6 +24,4 @@ void InheritableAttr::anchor() { } void InheritableParamAttr::anchor() { } -void MSInheritanceAttr::anchor() { } - #include "clang/AST/AttrImpl.inc" diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h index 89203f1..12b929b 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h +++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h @@ -44,7 +44,6 @@ public: }; /// Creates an instance of a C++ ABI class. -CXXABI *CreateARMCXXABI(ASTContext &Ctx); CXXABI *CreateItaniumCXXABI(ASTContext &Ctx); CXXABI *CreateMicrosoftCXXABI(ASTContext &Ctx); } diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index b51014b..6e80ee7 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -35,16 +35,12 @@ void CXXBasePaths::ComputeDeclsFound() { std::copy(Decls.begin(), Decls.end(), DeclsFound); } -CXXBasePaths::decl_iterator CXXBasePaths::found_decls_begin() { +CXXBasePaths::decl_range CXXBasePaths::found_decls() { if (NumDeclsFound == 0) ComputeDeclsFound(); - return DeclsFound; -} -CXXBasePaths::decl_iterator CXXBasePaths::found_decls_end() { - if (NumDeclsFound == 0) - ComputeDeclsFound(); - return DeclsFound + NumDeclsFound; + return decl_range(decl_iterator(DeclsFound), + decl_iterator(DeclsFound + NumDeclsFound)); } /// isAmbiguous - Determines whether the set of paths provided is @@ -62,7 +58,7 @@ void CXXBasePaths::clear() { Paths.clear(); ClassSubobjects.clear(); ScratchPath.clear(); - DetectedVirtual = 0; + DetectedVirtual = nullptr; } /// @brief Swaps the contents of this CXXBasePaths structure with the @@ -141,9 +137,8 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, const CXXRecordDecl *Record = this; bool AllMatches = true; while (true) { - for (CXXRecordDecl::base_class_const_iterator - I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { - const RecordType *Ty = I->getType()->getAs<RecordType>(); + for (const auto &I : Record->bases()) { + const RecordType *Ty = I.getType()->getAs<RecordType>(); if (!Ty) { if (AllowShortCircuit) return false; AllMatches = false; @@ -186,14 +181,11 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, AccessSpecifier AccessToHere = ScratchPath.Access; bool IsFirstStep = ScratchPath.empty(); - for (CXXRecordDecl::base_class_const_iterator BaseSpec = Record->bases_begin(), - BaseSpecEnd = Record->bases_end(); - BaseSpec != BaseSpecEnd; - ++BaseSpec) { + for (const auto &BaseSpec : Record->bases()) { // Find the record of the base class subobjects for this type. - QualType BaseType = Context.getCanonicalType(BaseSpec->getType()) - .getUnqualifiedType(); - + QualType BaseType = + Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType(); + // C++ [temp.dep]p3: // In the definition of a class template or a member of a class template, // if a base class of the class template depends on a template-parameter, @@ -208,10 +200,10 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType]; bool VisitBase = true; bool SetVirtual = false; - if (BaseSpec->isVirtual()) { + if (BaseSpec.isVirtual()) { VisitBase = !Subobjects.first; Subobjects.first = true; - if (isDetectingVirtual() && DetectedVirtual == 0) { + if (isDetectingVirtual() && DetectedVirtual == nullptr) { // If this is the first virtual we find, remember it. If it turns out // there is no base path here, we'll reset it later. DetectedVirtual = BaseType->getAs<RecordType>(); @@ -223,9 +215,9 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, if (isRecordingPaths()) { // Add this base specifier to the current path. CXXBasePathElement Element; - Element.Base = &*BaseSpec; + Element.Base = &BaseSpec; Element.Class = Record; - if (BaseSpec->isVirtual()) + if (BaseSpec.isVirtual()) Element.SubobjectNumber = 0; else Element.SubobjectNumber = Subobjects.second; @@ -247,16 +239,16 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, // 3. Otherwise, overall access is determined by the most restrictive // access in the sequence. if (IsFirstStep) - ScratchPath.Access = BaseSpec->getAccessSpecifier(); + ScratchPath.Access = BaseSpec.getAccessSpecifier(); else ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere, - BaseSpec->getAccessSpecifier()); + BaseSpec.getAccessSpecifier()); } // Track whether there's a path involving this specific base. bool FoundPathThroughBase = false; - if (BaseMatches(BaseSpec, ScratchPath, UserData)) { + if (BaseMatches(&BaseSpec, ScratchPath, UserData)) { // We've found a path that terminates at this base. FoundPath = FoundPathThroughBase = true; if (isRecordingPaths()) { @@ -269,7 +261,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, } } else if (VisitBase) { CXXRecordDecl *BaseRecord - = cast<CXXRecordDecl>(BaseSpec->getType()->castAs<RecordType>() + = cast<CXXRecordDecl>(BaseSpec.getType()->castAs<RecordType>() ->getDecl()); if (lookupInBases(Context, BaseRecord, BaseMatches, UserData)) { // C++ [class.member.lookup]p2: @@ -294,7 +286,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, // If we set a virtual earlier, and this isn't a path, forget it again. if (SetVirtual && !FoundPathThroughBase) { - DetectedVirtual = 0; + DetectedVirtual = nullptr; } } @@ -333,7 +325,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, for (CXXBasePath::iterator PE = P->begin(), PEEnd = P->end(); PE != PEEnd && !Hidden; ++PE) { if (PE->Base->isVirtual()) { - CXXRecordDecl *VBase = 0; + CXXRecordDecl *VBase = nullptr; if (const RecordType *Record = PE->Base->getType()->getAs<RecordType>()) VBase = cast<CXXRecordDecl>(Record->getDecl()); if (!VBase) @@ -347,7 +339,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, HidingPEnd = Paths.end(); HidingP != HidingPEnd; ++HidingP) { - CXXRecordDecl *HidingClass = 0; + CXXRecordDecl *HidingClass = nullptr; if (const RecordType *Record = HidingP->back().Base->getType()->getAs<RecordType>()) HidingClass = cast<CXXRecordDecl>(Record->getDecl()); @@ -501,14 +493,13 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, SubobjectNumber = ++SubobjectCount[cast<CXXRecordDecl>(RD->getCanonicalDecl())]; - for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(), - BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) { - if (const RecordType *RT = Base->getType()->getAs<RecordType>()) { + for (const auto &Base : RD->bases()) { + if (const RecordType *RT = Base.getType()->getAs<RecordType>()) { const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl()); if (!BaseDecl->isPolymorphic()) continue; - if (Overriders.empty() && !Base->isVirtual()) { + if (Overriders.empty() && !Base.isVirtual()) { // There are no other overriders of virtual member functions, // so let the base class fill in our overriders for us. Collect(BaseDecl, false, InVirtualSubobject, Overriders); @@ -522,7 +513,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, // its base classes) more than once. CXXFinalOverriderMap ComputedBaseOverriders; CXXFinalOverriderMap *BaseOverriders = &ComputedBaseOverriders; - if (Base->isVirtual()) { + if (Base.isVirtual()) { CXXFinalOverriderMap *&MyVirtualOverriders = VirtualOverriders[BaseDecl]; BaseOverriders = MyVirtualOverriders; if (!MyVirtualOverriders) { @@ -551,10 +542,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, } } - for (CXXRecordDecl::method_iterator M = RD->method_begin(), - MEnd = RD->method_end(); - M != MEnd; - ++M) { + for (auto *M : RD->methods()) { // We only care about virtual methods. if (!M->isVirtual()) continue; @@ -637,7 +625,7 @@ FinalOverriderCollector::~FinalOverriderCollector() { void CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const { FinalOverriderCollector Collector; - Collector.Collect(this, false, 0, FinalOverriders); + Collector.Collect(this, false, nullptr, FinalOverriders); // Weed out any final overriders that come from virtual base class // subobjects that were hidden by other subobjects along any path. @@ -702,13 +690,12 @@ AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, if (Layout.isPrimaryBaseVirtual()) Bases.insert(Layout.getPrimaryBase()); - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && + for (const auto &I : RD->bases()) { + assert(!I.getType()->isDependentType() && "Cannot get indirect primary bases for class with dependent bases."); const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); // Only bases with virtual bases participate in computing the // indirect primary virtual base classes. @@ -725,13 +712,12 @@ CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const { if (!getNumVBases()) return; - for (CXXRecordDecl::base_class_const_iterator I = bases_begin(), - E = bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && + for (const auto &I : bases()) { + assert(!I.getType()->isDependentType() && "Cannot get indirect primary bases for class with dependent bases."); const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); // Only bases with virtual bases participate in computing the // indirect primary virtual base classes. diff --git a/contrib/llvm/tools/clang/lib/AST/Comment.cpp b/contrib/llvm/tools/clang/lib/AST/Comment.cpp index f24a23d..4f43346 100644 --- a/contrib/llvm/tools/clang/lib/AST/Comment.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Comment.cpp @@ -136,7 +136,7 @@ void DeclInfo::fill() { IsInstanceMethod = false; IsClassMethod = false; ParamVars = None; - TemplateParameters = NULL; + TemplateParameters = nullptr; if (!CommentDecl) { // If there is no declaration, the defaults is our only guess. @@ -159,7 +159,7 @@ void DeclInfo::fill() { Kind = FunctionKind; ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), FD->getNumParams()); - ResultType = FD->getResultType(); + ReturnType = FD->getReturnType(); unsigned NumLists = FD->getNumTemplateParameterLists(); if (NumLists != 0) { TemplateKind = TemplateSpecialization; @@ -180,7 +180,7 @@ void DeclInfo::fill() { Kind = FunctionKind; ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(), MD->param_size()); - ResultType = MD->getResultType(); + ReturnType = MD->getReturnType(); IsObjCMethod = true; IsInstanceMethod = MD->isInstanceMethod(); IsClassMethod = !IsInstanceMethod; @@ -193,7 +193,7 @@ void DeclInfo::fill() { const FunctionDecl *FD = FTD->getTemplatedDecl(); ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), FD->getNumParams()); - ResultType = FD->getResultType(); + ReturnType = FD->getReturnType(); TemplateParameters = FTD->getTemplateParameters(); break; } @@ -251,6 +251,16 @@ void DeclInfo::fill() { TL = PointerTL.getPointeeLoc().getUnqualifiedLoc(); continue; } + // Look through reference types. + if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) { + TL = ReferenceTL.getPointeeLoc().getUnqualifiedLoc(); + continue; + } + // Look through adjusted types. + if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) { + TL = ATL.getOriginalLoc(); + continue; + } if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>()) { TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); @@ -261,13 +271,39 @@ void DeclInfo::fill() { TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); continue; } + if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) { + TL = ETL.getNamedTypeLoc(); + continue; + } // Is this a typedef for a function type? if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { Kind = FunctionKind; ArrayRef<ParmVarDecl *> Params = FTL.getParams(); ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(), Params.size()); - ResultType = FTL.getResultLoc().getType(); + ReturnType = FTL.getReturnLoc().getType(); + break; + } + if (TemplateSpecializationTypeLoc STL = + TL.getAs<TemplateSpecializationTypeLoc>()) { + // If we have a typedef to a template specialization with exactly one + // template argument of a function type, this looks like std::function, + // boost::function, or other function wrapper. Treat these typedefs as + // functions. + if (STL.getNumArgs() != 1) + break; + TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); + if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) + break; + TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); + TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); + if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { + Kind = FunctionKind; + ArrayRef<ParmVarDecl *> Params = FTL.getParams(); + ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(), + Params.size()); + ReturnType = FTL.getReturnLoc().getType(); + } break; } break; diff --git a/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp b/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp index 01bd12e..a7b07a4 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentCommandTraits.cpp @@ -43,47 +43,42 @@ const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const { return getRegisteredCommandInfo(CommandID); } -static void -HelperTypoCorrectCommandInfo(SmallVectorImpl<const CommandInfo *> &BestCommand, - StringRef Typo, const CommandInfo *Command) { - const unsigned MaxEditDistance = 1; - unsigned BestEditDistance = MaxEditDistance + 1; - StringRef Name = Command->Name; - - unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size()); - if (MinPossibleEditDistance > 0 && - Typo.size() / MinPossibleEditDistance < 1) - return; - unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance); - if (EditDistance > MaxEditDistance) - return; - if (EditDistance == BestEditDistance) - BestCommand.push_back(Command); - else if (EditDistance < BestEditDistance) { - BestCommand.clear(); - BestCommand.push_back(Command); - BestEditDistance = EditDistance; - } -} - const CommandInfo * CommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const { - // single character command impostures, such as \t or \n must not go + // Single-character command impostures, such as \t or \n, should not go // through the fixit logic. if (Typo.size() <= 1) - return NULL; - + return nullptr; + + // The maximum edit distance we're prepared to accept. + const unsigned MaxEditDistance = 1; + + unsigned BestEditDistance = MaxEditDistance; SmallVector<const CommandInfo *, 2> BestCommand; - - const int NumOfCommands = llvm::array_lengthof(Commands); - for (int i = 0; i < NumOfCommands; i++) - HelperTypoCorrectCommandInfo(BestCommand, Typo, &Commands[i]); - - for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) - if (!RegisteredCommands[i]->IsUnknownCommand) - HelperTypoCorrectCommandInfo(BestCommand, Typo, RegisteredCommands[i]); - - return (BestCommand.size() != 1) ? NULL : BestCommand[0]; + + auto ConsiderCorrection = [&](const CommandInfo *Command) { + StringRef Name = Command->Name; + + unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size()); + if (MinPossibleEditDistance <= BestEditDistance) { + unsigned EditDistance = Typo.edit_distance(Name, true, BestEditDistance); + if (EditDistance < BestEditDistance) { + BestEditDistance = EditDistance; + BestCommand.clear(); + } + if (EditDistance == BestEditDistance) + BestCommand.push_back(Command); + } + }; + + for (const auto &Command : Commands) + ConsiderCorrection(&Command); + + for (const auto *Command : RegisteredCommands) + if (!Command->IsUnknownCommand) + ConsiderCorrection(Command); + + return BestCommand.size() == 1 ? BestCommand[0] : nullptr; } CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) { @@ -118,7 +113,7 @@ const CommandInfo *CommandTraits::getBuiltinCommandInfo( unsigned CommandID) { if (CommandID < llvm::array_lengthof(Commands)) return &Commands[CommandID]; - return NULL; + return nullptr; } const CommandInfo *CommandTraits::getRegisteredCommandInfo( @@ -127,7 +122,7 @@ const CommandInfo *CommandTraits::getRegisteredCommandInfo( if (RegisteredCommands[i]->Name == Name) return RegisteredCommands[i]; } - return NULL; + return nullptr; } const CommandInfo *CommandTraits::getRegisteredCommandInfo( diff --git a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp index 01ed3ce..792a832 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentLexer.cpp @@ -268,6 +268,19 @@ const char *findCCommentEnd(const char *BufferPtr, const char *BufferEnd) { } // unnamed namespace +void Lexer::formTokenWithChars(Token &Result, const char *TokEnd, + tok::TokenKind Kind) { + const unsigned TokLen = TokEnd - BufferPtr; + Result.setLocation(getSourceLocation(BufferPtr)); + Result.setKind(Kind); + Result.setLength(TokLen); +#ifndef NDEBUG + Result.TextPtr = "<UNSET>"; + Result.IntVal = 7; +#endif + BufferPtr = TokEnd; +} + void Lexer::lexCommentText(Token &T) { assert(CommentState == LCS_InsideBCPLComment || CommentState == LCS_InsideCComment); diff --git a/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp b/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp index 03e0101..cb37ec3 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentParser.cpp @@ -311,9 +311,9 @@ void Parser::parseBlockCommandArgs(BlockCommandComment *BC, BlockCommandComment *Parser::parseBlockCommand() { assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command)); - ParamCommandComment *PC = 0; - TParamCommandComment *TPC = 0; - BlockCommandComment *BC = 0; + ParamCommandComment *PC = nullptr; + TParamCommandComment *TPC = nullptr; + BlockCommandComment *BC = nullptr; const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID()); CommandMarkerKind CommandMarker = Tok.is(tok::backslash_command) ? CMK_Backslash : CMK_At; diff --git a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp index 1c6222f..12823c3 100644 --- a/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CommentSema.cpp @@ -29,7 +29,8 @@ Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, DiagnosticsEngine &Diags, CommandTraits &Traits, const Preprocessor *PP) : Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits), - PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), HeaderfileCommand(NULL) { + PP(PP), ThisDeclInfo(nullptr), BriefCommand(nullptr), + HeaderfileCommand(nullptr) { } void Sema::setDecl(const Decl *D) { @@ -68,8 +69,12 @@ void Sema::actOnBlockCommandFinish(BlockCommandComment *Command, Command->setParagraph(Paragraph); checkBlockCommandEmptyParagraph(Command); checkBlockCommandDuplicate(Command); - checkReturnsCommand(Command); - checkDeprecatedCommand(Command); + if (ThisDeclInfo) { + // These checks only make sense if the comment is attached to a + // declaration. + checkReturnsCommand(Command); + checkDeprecatedCommand(Command); + } } ParamCommandComment *Sema::actOnParamCommandStart( @@ -122,7 +127,7 @@ void Sema::checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment) { << (DiagSelect-1) << (DiagSelect-1) << Comment->getSourceRange(); } - + void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) { const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID()); if (!Info->IsRecordLikeDeclarationCommand) @@ -478,6 +483,7 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin, if (isHTMLEndTagForbidden(TagName)) { Diag(HET->getLocation(), diag::warn_doc_html_end_forbidden) << TagName << HET->getSourceRange(); + HET->setIsMalformed(); return HET; } @@ -493,14 +499,19 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin, if (!FoundOpen) { Diag(HET->getLocation(), diag::warn_doc_html_end_unbalanced) << HET->getSourceRange(); + HET->setIsMalformed(); return HET; } while (!HTMLOpenTags.empty()) { - const HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val(); + HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val(); StringRef LastNotClosedTagName = HST->getTagName(); - if (LastNotClosedTagName == TagName) + if (LastNotClosedTagName == TagName) { + // If the start tag is malformed, end tag is malformed as well. + if (HST->isMalformed()) + HET->setIsMalformed(); break; + } if (isHTMLEndTagOptional(LastNotClosedTagName)) continue; @@ -514,16 +525,18 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin, HET->getLocation(), &CloseLineInvalid); - if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) + if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) { Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch) << HST->getTagName() << HET->getTagName() << HST->getSourceRange() << HET->getSourceRange(); - else { + HST->setIsMalformed(); + } else { Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch) << HST->getTagName() << HET->getTagName() << HST->getSourceRange(); Diag(HET->getLocation(), diag::note_doc_html_end_tag) << HET->getSourceRange(); + HST->setIsMalformed(); } } @@ -534,6 +547,18 @@ FullComment *Sema::actOnFullComment( ArrayRef<BlockContentComment *> Blocks) { FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo); resolveParamCommandIndexes(FC); + + // Complain about HTML tags that are not closed. + while (!HTMLOpenTags.empty()) { + HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val(); + if (isHTMLEndTagOptional(HST->getTagName())) + continue; + + Diag(HST->getLocation(), diag::warn_doc_html_missing_end_tag) + << HST->getTagName() << HST->getSourceRange(); + HST->setIsMalformed(); + } + return FC; } @@ -558,8 +583,11 @@ void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) { void Sema::checkReturnsCommand(const BlockCommandComment *Command) { if (!Traits.getCommandInfo(Command->getCommandID())->IsReturnsCommand) return; + + assert(ThisDeclInfo && "should not call this check on a bare comment"); + if (isFunctionDecl()) { - if (ThisDeclInfo->ResultType->isVoidType()) { + if (ThisDeclInfo->ReturnType->isVoidType()) { unsigned DiagKind; switch (ThisDeclInfo->CommentDecl->getKind()) { default: @@ -586,7 +614,7 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { } else if (isObjCPropertyDecl()) return; - + Diag(Command->getLocation(), diag::warn_doc_returns_not_attached_to_a_function_decl) << Command->getCommandMarker() @@ -596,7 +624,7 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID()); - const BlockCommandComment *PrevCommand = NULL; + const BlockCommandComment *PrevCommand = nullptr; if (Info->IsBriefCommand) { if (!BriefCommand) { BriefCommand = Command; @@ -636,6 +664,8 @@ void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) { if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand) return; + assert(ThisDeclInfo && "should not call this check on a bare comment"); + const Decl *D = ThisDeclInfo->CommentDecl; if (!D) return; @@ -694,7 +724,7 @@ void Sema::resolveParamCommandIndexes(const FullComment *FC) { SmallVector<ParamCommandComment *, 8> ParamVarDocs; ArrayRef<const ParmVarDecl *> ParamVars = getParamVars(); - ParamVarDocs.resize(ParamVars.size(), NULL); + ParamVarDocs.resize(ParamVars.size(), nullptr); // First pass over all \\param commands: resolve all parameter names. for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end(); @@ -783,11 +813,14 @@ bool Sema::isAnyFunctionDecl() { } bool Sema::isFunctionOrMethodVariadic() { - if (!isAnyFunctionDecl() && !isObjCMethodDecl()) + if (!isAnyFunctionDecl() && !isObjCMethodDecl() && !isFunctionTemplateDecl()) return false; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDeclInfo->CurrentDecl)) return FD->isVariadic(); + if (const FunctionTemplateDecl *FTD = + dyn_cast<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl)) + return FTD->getTemplatedDecl()->isVariadic(); if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl)) return MD->isVariadic(); @@ -812,7 +845,7 @@ bool Sema::isFunctionPointerVarDecl() { } return false; } - + bool Sema::isObjCPropertyDecl() { if (!ThisDeclInfo) return false; @@ -834,8 +867,8 @@ bool Sema::isRecordLikeDecl() { return false; if (!ThisDeclInfo->IsFilled) inspectThisDecl(); - return isUnionDecl() || isClassOrStructDecl() - || isObjCInterfaceDecl() || isObjCProtocolDecl(); + return isUnionDecl() || isClassOrStructDecl() || isObjCInterfaceDecl() || + isObjCProtocolDecl(); } bool Sema::isUnionDecl() { @@ -848,7 +881,7 @@ bool Sema::isUnionDecl() { return RD->isUnion(); return false; } - + bool Sema::isClassOrStructDecl() { if (!ThisDeclInfo) return false; @@ -858,7 +891,7 @@ bool Sema::isClassOrStructDecl() { isa<RecordDecl>(ThisDeclInfo->CurrentDecl) && !isUnionDecl(); } - + bool Sema::isClassTemplateDecl() { if (!ThisDeclInfo) return false; @@ -874,7 +907,7 @@ bool Sema::isFunctionTemplateDecl() { if (!ThisDeclInfo->IsFilled) inspectThisDecl(); return ThisDeclInfo->CurrentDecl && - (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl)); + (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl)); } bool Sema::isObjCInterfaceDecl() { @@ -885,7 +918,7 @@ bool Sema::isObjCInterfaceDecl() { return ThisDeclInfo->CurrentDecl && isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl); } - + bool Sema::isObjCProtocolDecl() { if (!ThisDeclInfo) return false; @@ -894,7 +927,7 @@ bool Sema::isObjCProtocolDecl() { return ThisDeclInfo->CurrentDecl && isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl); } - + ArrayRef<const ParmVarDecl *> Sema::getParamVars() { if (!ThisDeclInfo->IsFilled) inspectThisDecl(); @@ -930,7 +963,7 @@ class SimpleTypoCorrector { public: SimpleTypoCorrector(StringRef Typo) : Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3), - BestDecl(NULL), BestEditDistance(MaxEditDistance + 1), + BestDecl(nullptr), BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) { } @@ -938,7 +971,7 @@ public: const NamedDecl *getBestDecl() const { if (BestEditDistance > MaxEditDistance) - return NULL; + return nullptr; return BestDecl; } diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index 6bd9858..7448de2 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -13,6 +13,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" @@ -29,7 +30,6 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/type_traits.h" #include <algorithm> using namespace clang; @@ -158,8 +158,7 @@ static bool usesTypeVisibility(const NamedDecl *D) { /// Does the given declaration have member specialization information, /// and if so, is it an explicit specialization? template <class T> static typename -llvm::enable_if_c<!llvm::is_base_of<RedeclarableTemplateDecl, T>::value, - bool>::type +std::enable_if<!std::is_base_of<RedeclarableTemplateDecl, T>::value, bool>::type isExplicitMemberSpecialization(const T *D) { if (const MemberSpecializationInfo *member = D->getMemberSpecializationInfo()) { @@ -209,11 +208,8 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D, // If we're on Mac OS X, an 'availability' for Mac OS X attribute // implies visibility(default). if (D->getASTContext().getTargetInfo().getTriple().isOSDarwin()) { - for (specific_attr_iterator<AvailabilityAttr> - A = D->specific_attr_begin<AvailabilityAttr>(), - AEnd = D->specific_attr_end<AvailabilityAttr>(); - A != AEnd; ++A) - if ((*A)->getPlatform()->getName().equals("macosx")) + for (const auto *A : D->specific_attrs<AvailabilityAttr>()) + if (A->getPlatform()->getName().equals("macosx")) return DefaultVisibility; } @@ -231,23 +227,21 @@ getLVForType(const Type &T, LVComputationKind computation) { /// template parameter list. For visibility purposes, template /// parameters are part of the signature of a template. static LinkageInfo -getLVForTemplateParameterList(const TemplateParameterList *params, +getLVForTemplateParameterList(const TemplateParameterList *Params, LVComputationKind computation) { LinkageInfo LV; - for (TemplateParameterList::const_iterator P = params->begin(), - PEnd = params->end(); - P != PEnd; ++P) { - + for (const NamedDecl *P : *Params) { // Template type parameters are the most common and never // contribute to visibility, pack or not. - if (isa<TemplateTypeParmDecl>(*P)) + if (isa<TemplateTypeParmDecl>(P)) continue; // Non-type template parameters can be restricted by the value type, e.g. // template <enum X> class A { ... }; // We have to be careful here, though, because we can be dealing with // dependent types. - if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { + if (const NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(P)) { // Handle the non-pack case first. if (!NTTP->isExpandedParameterPack()) { if (!NTTP->getType()->isDependentType()) { @@ -267,7 +261,7 @@ getLVForTemplateParameterList(const TemplateParameterList *params, // Template template parameters can be restricted by their // template parameters, recursively. - TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); + const TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(P); // Handle the non-pack case first. if (!TTP->isExpandedParameterPack()) { @@ -292,7 +286,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation); static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { - const Decl *Ret = NULL; + const Decl *Ret = nullptr; const DeclContext *DC = D->getDeclContext(); while (DC->getDeclKind() != Decl::TranslationUnit) { if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC)) @@ -307,43 +301,41 @@ static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { /// /// Note that we don't take an LVComputationKind because we always /// want to honor the visibility of template arguments in the same way. -static LinkageInfo -getLVForTemplateArgumentList(ArrayRef<TemplateArgument> args, - LVComputationKind computation) { +static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, + LVComputationKind computation) { LinkageInfo LV; - for (unsigned i = 0, e = args.size(); i != e; ++i) { - const TemplateArgument &arg = args[i]; - switch (arg.getKind()) { + for (const TemplateArgument &Arg : Args) { + switch (Arg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Expression: continue; case TemplateArgument::Type: - LV.merge(getLVForType(*arg.getAsType(), computation)); + LV.merge(getLVForType(*Arg.getAsType(), computation)); continue; case TemplateArgument::Declaration: - if (NamedDecl *ND = dyn_cast<NamedDecl>(arg.getAsDecl())) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) { assert(!usesTypeVisibility(ND)); LV.merge(getLVForDecl(ND, computation)); } continue; case TemplateArgument::NullPtr: - LV.merge(arg.getNullPtrType()->getLinkageAndVisibility()); + LV.merge(Arg.getNullPtrType()->getLinkageAndVisibility()); continue; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - if (TemplateDecl *Template - = arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) + if (TemplateDecl *Template = + Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) LV.merge(getLVForDecl(Template, computation)); continue; case TemplateArgument::Pack: - LV.merge(getLVForTemplateArgumentList(arg.getPackAsArray(), computation)); + LV.merge(getLVForTemplateArgumentList(Arg.getPackAsArray(), computation)); continue; } llvm_unreachable("bad template argument kind"); @@ -479,6 +471,58 @@ static void mergeTemplateLV(LinkageInfo &LV, LV.mergeExternalVisibility(argsLV); } +/// Should we consider visibility associated with the template +/// arguments and parameters of the given variable template +/// specialization? As usual, follow class template specialization +/// logic up to initialization. +static bool shouldConsiderTemplateVisibility( + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation) { + // Include visibility from the template parameters and arguments + // only if this is not an explicit instantiation or specialization + // with direct explicit visibility (and note that implicit + // instantiations won't have a direct attribute). + if (!spec->isExplicitInstantiationOrSpecialization()) + return true; + + // An explicit variable specialization is an independent, top-level + // declaration. As such, if it has an explicit visibility attribute, + // that must directly express the user's intent, and we should honor + // it. + if (spec->isExplicitSpecialization() && + hasExplicitVisibilityAlready(computation)) + return false; + + return !hasDirectVisibilityAttribute(spec, computation); +} + +/// Merge in template-related linkage and visibility for the given +/// variable template specialization. As usual, follow class template +/// specialization logic up to initialization. +static void mergeTemplateLV(LinkageInfo &LV, + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation) { + bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); + + // Merge information from the template parameters, but ignore + // visibility if we're only considering template arguments. + + VarTemplateDecl *temp = spec->getSpecializedTemplate(); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); + LV.mergeMaybeWithVisibility(tempLV, + considerVisibility && !hasExplicitVisibilityAlready(computation)); + + // Merge information from the template arguments. We ignore + // template-argument visibility if we've got an explicit + // instantiation with a visibility attribute. + const TemplateArgumentList &templateArgs = spec->getTemplateArgs(); + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation); + if (considerVisibility) + LV.mergeVisibility(argsLV); + LV.mergeExternalVisibility(argsLV); +} + static bool useInlineVisibilityHidden(const NamedDecl *D) { // FIXME: we should warn if -fvisibility-inlines-hidden is used with c. const LangOptions &Opts = D->getASTContext().getLangOpts(); @@ -498,7 +542,7 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) { TSK = MSI->getTemplateSpecializationKind(); } - const FunctionDecl *Def = 0; + const FunctionDecl *Def = nullptr; // InlineVisibilityHidden only applies to definitions, and // isInlined() only gives meaningful answers on definitions // anyway. @@ -512,9 +556,9 @@ template <typename T> static bool isFirstInExternCContext(T *D) { return First->isInExternCContext(); } -static bool isSingleLineExternC(const Decl &D) { +static bool isSingleLineLanguageLinkage(const Decl &D) { if (const LinkageSpecDecl *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext())) - if (SD->getLanguage() == LinkageSpecDecl::lang_c && !SD->hasBraces()) + if (!SD->hasBraces()) return true; return false; } @@ -548,7 +592,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (Var->getStorageClass() != SC_Extern && Var->getStorageClass() != SC_PrivateExtern && - !isSingleLineExternC(*Var)) + !isSingleLineLanguageLinkage(*Var)) return LinkageInfo::internal(); } @@ -561,16 +605,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (PrevVar->getStorageClass() == SC_Static) return LinkageInfo::internal(); } - } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) { + } else if (const FunctionDecl *Function = D->getAsFunction()) { // C++ [temp]p4: // A non-member function template can have internal linkage; any // other template name shall have external linkage. - const FunctionDecl *Function = 0; - if (const FunctionTemplateDecl *FunTmpl - = dyn_cast<FunctionTemplateDecl>(D)) - Function = FunTmpl->getTemplatedDecl(); - else - Function = cast<FunctionDecl>(D); // Explicitly declared static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) @@ -676,6 +714,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // C99 6.2.2p4 and propagating the visibility attribute, so we don't have // to do it here. + // As per function and class template specializations (below), + // consider LV for the template and template arguments. We're at file + // scope, so we do not need to worry about nested specializations. + if (const VarTemplateSpecializationDecl *spec + = dyn_cast<VarTemplateSpecializationDecl>(Var)) { + mergeTemplateLV(LV, spec, computation); + } + // - a function, unless it has internal linkage; or } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { // In theory, we can modify the function's LV by the LV of its @@ -782,11 +828,18 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // really have linkage, but it's convenient to say they do for the // purposes of calculating linkage of pointer-to-data-member // template arguments. + // + // Templates also don't officially have linkage, but since we ignore + // the C++ standard and look at template arguments when determining + // linkage and visibility of a template specialization, we might hit + // a template template argument that way. If we do, we need to + // consider its linkage. if (!(isa<CXXMethodDecl>(D) || isa<VarDecl>(D) || isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || - isa<TagDecl>(D))) + isa<TagDecl>(D) || + isa<TemplateDecl>(D))) return LinkageInfo::none(); LinkageInfo LV; @@ -825,7 +878,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // we need to completely ignore the visibility from it. // Specifically, if this decl exists and has an explicit attribute. - const NamedDecl *explicitSpecSuppressor = 0; + const NamedDecl *explicitSpecSuppressor = nullptr; if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { // If the type of the function uses a type with unique-external @@ -876,6 +929,10 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // Static data members. } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (const VarTemplateSpecializationDecl *spec + = dyn_cast<VarTemplateSpecializationDecl>(VD)) + mergeTemplateLV(LV, spec, computation); + // Modify the variable's linkage by its type, but ignore the // type's visibility unless it's a definition. LinkageInfo typeLV = getLVForType(*VD->getType(), computation); @@ -989,6 +1046,10 @@ getExplicitVisibilityAux(const NamedDecl *ND, return getVisibilityOf(InstantiatedFrom, kind); } + if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Var)) + return getVisibilityOf(VTSD->getSpecializedTemplate()->getTemplatedDecl(), + kind); + return None; } // Also handle function template specializations. @@ -1242,16 +1303,13 @@ public: // We have just computed the linkage for this decl. By induction we know // that all other computed linkages match, check that the one we just - // computed - // also does. - NamedDecl *Old = NULL; - for (NamedDecl::redecl_iterator I = D->redecls_begin(), - E = D->redecls_end(); - I != E; ++I) { - NamedDecl *T = cast<NamedDecl>(*I); + // computed also does. + NamedDecl *Old = nullptr; + for (auto I : D->redecls()) { + NamedDecl *T = cast<NamedDecl>(I); if (T == D) continue; - if (T->hasCachedLinkage()) { + if (!T->isInvalidDecl() && T->hasCachedLinkage()) { Old = T; break; } @@ -1270,13 +1328,9 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, } std::string NamedDecl::getQualifiedNameAsString() const { - return getQualifiedNameAsString(getASTContext().getPrintingPolicy()); -} - -std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { std::string QualName; llvm::raw_string_ostream OS(QualName); - printQualifiedName(OS, P); + printQualifiedName(OS, getASTContext().getPrintingPolicy()); return OS.str(); } @@ -1313,17 +1367,20 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, TemplateArgs.size(), P); } else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(*I)) { + if (P.SuppressUnwrittenScope && + (ND->isAnonymousNamespace() || ND->isInline())) + continue; if (ND->isAnonymousNamespace()) - OS << "<anonymous namespace>"; + OS << "(anonymous namespace)"; else OS << *ND; } else if (const RecordDecl *RD = dyn_cast<RecordDecl>(*I)) { if (!RD->getIdentifier()) - OS << "<anonymous " << RD->getKindName() << '>'; + OS << "(anonymous " << RD->getKindName() << ')'; else OS << *RD; } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { - const FunctionProtoType *FT = 0; + const FunctionProtoType *FT = nullptr; if (FD->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>()); @@ -1352,7 +1409,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, if (getDeclName()) OS << *this; else - OS << "<anonymous>"; + OS << "(anonymous)"; } void NamedDecl::getNameForDiagnostic(raw_ostream &OS, @@ -1392,6 +1449,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { if (isa<ObjCMethodDecl>(this)) return false; + // FIXME: Is this correct if one of the decls comes from an inline namespace? if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD)) return true; @@ -1418,14 +1476,19 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { // A typedef of an Objective-C class type can replace an Objective-C class // declaration or definition, and vice versa. + // FIXME: Is this correct if one of the decls comes from an inline namespace? if ((isa<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) || (isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(OldD))) return true; - + // For non-function declarations, if the declarations are of the - // same kind then this must be a redeclaration, or semantic analysis - // would not have given us the new declaration. - return this->getKind() == OldD->getKind(); + // same kind and have the same parent then this must be a redeclaration, + // or semantic analysis would not have given us the new declaration. + // Note that inline namespaces can give us two declarations with the same + // name and kind in the same scope but different contexts. + return this->getKind() == OldD->getKind() && + this->getDeclContext()->getRedeclContext()->Equals( + OldD->getDeclContext()->getRedeclContext()); } bool NamedDecl::hasLinkage() const { @@ -1453,11 +1516,9 @@ bool NamedDecl::isCXXInstanceMember() const { if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D)) return true; - if (isa<CXXMethodDecl>(D)) - return cast<CXXMethodDecl>(D)->isInstance(); - if (isa<FunctionTemplateDecl>(D)) - return cast<CXXMethodDecl>(cast<FunctionTemplateDecl>(D) - ->getTemplatedDecl())->isInstance(); + if (const CXXMethodDecl *MD = + dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction())) + return MD->isInstance(); return false; } @@ -1574,7 +1635,9 @@ bool typeIsPostfix(clang::QualType QT) { SourceRange DeclaratorDecl::getSourceRange() const { SourceLocation RangeEnd = getLocation(); if (TypeSourceInfo *TInfo = getTypeSourceInfo()) { - if (typeIsPostfix(TInfo->getType())) + // If the declaration has no name or the type extends past the name take the + // end location of the type. + if (!getDeclName() || typeIsPostfix(TInfo->getType())) RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); } return SourceRange(getOuterLocStart(), RangeEnd); @@ -1584,13 +1647,13 @@ void QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, TemplateParameterList **TPLists) { - assert((NumTPLists == 0 || TPLists != 0) && + assert((NumTPLists == 0 || TPLists != nullptr) && "Empty array of template parameters with positive size!"); // Free previous template parameters (if any). if (NumTemplParamLists > 0) { Context.Deallocate(TemplParamLists); - TemplParamLists = 0; + TemplParamLists = nullptr; NumTemplParamLists = 0; } // Set info on matched template parameter lists (if any). @@ -1620,12 +1683,16 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { llvm_unreachable("Invalid storage class"); } -VarDecl::VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo, StorageClass SC) - : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() { - assert(sizeof(VarDeclBitfields) <= sizeof(unsigned)); - assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned)); +VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + StorageClass SC) + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), + redeclarable_base(C), Init() { + static_assert(sizeof(VarDeclBitfields) <= sizeof(unsigned), + "VarDeclBitfields too large!"); + static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned), + "ParmVarDeclBitfields too large!"); AllBits = 0; VarDeclBits.SClass = SC; // Everything else is implicitly initialized to false. @@ -1635,13 +1702,13 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL, SourceLocation IdL, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S) { - return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S); + return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S); } VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarDecl)); - return new (Mem) VarDecl(Var, 0, SourceLocation(), SourceLocation(), 0, - QualType(), 0, SC_None); + return new (C, ID) + VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr, + QualType(), nullptr, SC_None); } void VarDecl::setStorageClass(StorageClass SC) { @@ -1649,6 +1716,21 @@ void VarDecl::setStorageClass(StorageClass SC) { VarDeclBits.SClass = SC; } +VarDecl::TLSKind VarDecl::getTLSKind() const { + switch (VarDeclBits.TSCSpec) { + case TSCS_unspecified: + if (hasAttr<ThreadAttr>()) + return TLS_Static; + return TLS_None; + case TSCS___thread: // Fall through. + case TSCS__Thread_local: + return TLS_Static; + case TSCS_thread_local: + return TLS_Dynamic; + } + llvm_unreachable("Unknown thread storage class specifier!"); +} + SourceRange VarDecl::getSourceRange() const { if (const Expr *Init = getInit()) { SourceLocation InitEnd = Init->getLocEnd(); @@ -1661,7 +1743,7 @@ SourceRange VarDecl::getSourceRange() const { } template<typename T> -static LanguageLinkage getLanguageLinkageTemplate(const T &D) { +static LanguageLinkage getDeclLanguageLinkage(const T &D) { // C++ [dcl.link]p1: All function types, function names with external linkage, // and variable names with external linkage have a language linkage. if (!D.hasExternalFormalLinkage()) @@ -1689,7 +1771,7 @@ static LanguageLinkage getLanguageLinkageTemplate(const T &D) { } template<typename T> -static bool isExternCTemplate(const T &D) { +static bool isDeclExternC(const T &D) { // Since the context is ignored for class members, they can only have C++ // language linkage or no language linkage. const DeclContext *DC = D.getDeclContext(); @@ -1702,11 +1784,11 @@ static bool isExternCTemplate(const T &D) { } LanguageLinkage VarDecl::getLanguageLinkage() const { - return getLanguageLinkageTemplate(*this); + return getDeclLanguageLinkage(*this); } bool VarDecl::isExternC() const { - return isExternCTemplate(*this); + return isDeclExternC(*this); } bool VarDecl::isInExternCContext() const { @@ -1775,7 +1857,7 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( // A declaration directly contained in a linkage-specification is treated // as if it contains the extern specifier for the purpose of determining // the linkage of the declared name and whether it is a definition. - if (isSingleLineExternC(*this)) + if (isSingleLineLanguageLinkage(*this)) return DeclarationOnly; // C99 6.9.2p2: @@ -1794,38 +1876,35 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( VarDecl *VarDecl::getActingDefinition() { DefinitionKind Kind = isThisDeclarationADefinition(); if (Kind != TentativeDefinition) - return 0; + return nullptr; - VarDecl *LastTentative = 0; + VarDecl *LastTentative = nullptr; VarDecl *First = getFirstDecl(); - for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); - I != E; ++I) { - Kind = (*I)->isThisDeclarationADefinition(); + for (auto I : First->redecls()) { + Kind = I->isThisDeclarationADefinition(); if (Kind == Definition) - return 0; + return nullptr; else if (Kind == TentativeDefinition) - LastTentative = *I; + LastTentative = I; } return LastTentative; } VarDecl *VarDecl::getDefinition(ASTContext &C) { VarDecl *First = getFirstDecl(); - for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); - I != E; ++I) { - if ((*I)->isThisDeclarationADefinition(C) == Definition) - return *I; + for (auto I : First->redecls()) { + if (I->isThisDeclarationADefinition(C) == Definition) + return I; } - return 0; + return nullptr; } VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { DefinitionKind Kind = DeclarationOnly; const VarDecl *First = getFirstDecl(); - for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); - I != E; ++I) { - Kind = std::max(Kind, (*I)->isThisDeclarationADefinition(C)); + for (auto I : First->redecls()) { + Kind = std::max(Kind, I->isThisDeclarationADefinition(C)); if (Kind == Definition) break; } @@ -1834,15 +1913,13 @@ VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { } const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const { - redecl_iterator I = redecls_begin(), E = redecls_end(); - while (I != E && !I->getInit()) - ++I; - - if (I != E) { - D = *I; - return I->getInit(); + for (auto I : redecls()) { + if (auto Expr = I->getInit()) { + D = I; + return Expr; + } } - return 0; + return nullptr; } bool VarDecl::isOutOfLine() const { @@ -1863,15 +1940,14 @@ bool VarDecl::isOutOfLine() const { VarDecl *VarDecl::getOutOfLineDefinition() { if (!isStaticDataMember()) - return 0; - - for (VarDecl::redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); - RD != RDEnd; ++RD) { + return nullptr; + + for (auto RD : redecls()) { if (RD->getLexicalDeclContext()->isFileContext()) - return *RD; + return RD; } - - return 0; + + return nullptr; } void VarDecl::setInit(Expr *I) { @@ -1948,7 +2024,7 @@ APValue *VarDecl::evaluateValue( // first time it is evaluated. FIXME: The notes won't always be emitted the // first time we try evaluation, so might not be produced at all. if (Eval->WasEvaluated) - return Eval->Evaluated.isUninit() ? 0 : &Eval->Evaluated; + return Eval->Evaluated.isUninit() ? nullptr : &Eval->Evaluated; const Expr *Init = cast<Expr>(Eval->Value); assert(!Init->isValueDependent()); @@ -1957,7 +2033,7 @@ APValue *VarDecl::evaluateValue( // FIXME: Produce a diagnostic for self-initialization. Eval->CheckedICE = true; Eval->IsICE = false; - return 0; + return nullptr; } Eval->IsEvaluating = true; @@ -1983,7 +2059,7 @@ APValue *VarDecl::evaluateValue( Eval->IsICE = Result && Notes.empty(); } - return Result ? &Eval->Evaluated : 0; + return Result ? &Eval->Evaluated : nullptr; } bool VarDecl::checkInitIsICE() const { @@ -2025,8 +2101,8 @@ bool VarDecl::checkInitIsICE() const { VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) return cast<VarDecl>(MSI->getInstantiatedFrom()); - - return 0; + + return nullptr; } TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const { @@ -2066,7 +2142,7 @@ MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const { // return getASTContext().getInstantiatedFromStaticDataMember(this); return getASTContext().getTemplateOrSpecializationInfo(this) .dyn_cast<MemberSpecializationInfo *>(); - return 0; + return nullptr; } void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, @@ -2108,8 +2184,8 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg) { - return new (C) ParmVarDecl(ParmVar, DC, StartLoc, IdLoc, Id, T, TInfo, - S, DefArg); + return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo, + S, DefArg); } QualType ParmVarDecl::getOriginalType() const { @@ -2121,9 +2197,9 @@ QualType ParmVarDecl::getOriginalType() const { } ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ParmVarDecl)); - return new (Mem) ParmVarDecl(ParmVar, 0, SourceLocation(), SourceLocation(), - 0, QualType(), 0, SC_None, 0); + return new (C, ID) + ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(), + nullptr, QualType(), nullptr, SC_None, nullptr); } SourceRange ParmVarDecl::getSourceRange() const { @@ -2196,9 +2272,9 @@ bool FunctionDecl::isVariadic() const { } bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + for (auto I : redecls()) { if (I->Body || I->IsLateTemplateParsed) { - Definition = *I; + Definition = I; return true; } } @@ -2221,10 +2297,10 @@ bool FunctionDecl::hasTrivialBody() const } bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + for (auto I : redecls()) { if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed || I->hasAttr<AliasAttr>()) { - Definition = I->IsDeleted ? I->getCanonicalDecl() : *I; + Definition = I->IsDeleted ? I->getCanonicalDecl() : I; return true; } } @@ -2234,12 +2310,12 @@ bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { if (!hasBody(Definition)) - return 0; + return nullptr; if (Definition->Body) return Definition->Body.get(getASTContext().getExternalSource()); - return 0; + return nullptr; } void FunctionDecl::setBody(Stmt *B) { @@ -2303,11 +2379,12 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { getDeclName().getCXXOverloadedOperator() == OO_Array_New || getDeclName().getCXXOverloadedOperator() == OO_Array_Delete); - if (isa<CXXRecordDecl>(getDeclContext())) return false; - assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return false; const FunctionProtoType *proto = getType()->castAs<FunctionProtoType>(); - if (proto->getNumArgs() != 2 || proto->isVariadic()) return false; + if (proto->getNumParams() != 2 || proto->isVariadic()) + return false; ASTContext &Context = cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()) @@ -2315,13 +2392,7 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { // The result type and first argument type are constant across all // these operators. The second argument must be exactly void*. - return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy); -} - -static bool isNamespaceStd(const DeclContext *DC) { - const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC->getRedeclContext()); - return ND && isNamed(ND, "std") && - ND->getParent()->getRedeclContext()->isTranslationUnit(); + return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy); } bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { @@ -2335,20 +2406,23 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { if (isa<CXXRecordDecl>(getDeclContext())) return false; - assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + + // This can only fail for an invalid 'operator new' declaration. + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return false; const FunctionProtoType *FPT = getType()->castAs<FunctionProtoType>(); - if (FPT->getNumArgs() > 2 || FPT->isVariadic()) + if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic()) return false; // If this is a single-parameter function, it must be a replaceable global // allocation or deallocation function. - if (FPT->getNumArgs() == 1) + if (FPT->getNumParams() == 1) return true; // Otherwise, we're looking for a second parameter whose type is // 'const std::nothrow_t &', or, in C++1y, 'std::size_t'. - QualType Ty = FPT->getArgType(1); + QualType Ty = FPT->getParamType(1); ASTContext &Ctx = getASTContext(); if (Ctx.getLangOpts().SizedDeallocation && Ctx.hasSameType(Ty, Ctx.getSizeType())) @@ -2358,30 +2432,31 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { Ty = Ty->getPointeeType(); if (Ty.getCVRQualifiers() != Qualifiers::Const) return false; - // FIXME: Recognise nothrow_t in an inline namespace inside std? const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - return RD && isNamed(RD, "nothrow_t") && isNamespaceStd(RD->getDeclContext()); + return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace(); } FunctionDecl * FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const { ASTContext &Ctx = getASTContext(); if (!Ctx.getLangOpts().SizedDeallocation) - return 0; + return nullptr; if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) - return 0; + return nullptr; if (getDeclName().getCXXOverloadedOperator() != OO_Delete && getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) - return 0; + return nullptr; if (isa<CXXRecordDecl>(getDeclContext())) - return 0; - assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + return nullptr; + + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return nullptr; if (getNumParams() != 2 || isVariadic() || - !Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getArgType(1), + !Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getParamType(1), Ctx.getSizeType())) - return 0; + return nullptr; // This is a sized deallocation function. Find the corresponding unsized // deallocation function. @@ -2391,15 +2466,15 @@ FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*RI)) if (FD->getNumParams() == 1 && !FD->isVariadic()) return FD; - return 0; + return nullptr; } LanguageLinkage FunctionDecl::getLanguageLinkage() const { - return getLanguageLinkageTemplate(*this); + return getDeclLanguageLinkage(*this); } bool FunctionDecl::isExternC() const { - return isExternCTemplate(*this); + return isDeclExternC(*this); } bool FunctionDecl::isInExternCContext() const { @@ -2442,7 +2517,7 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { FunctionTemplateDecl *PrevFunTmpl - = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0; + = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : nullptr; assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); FunTmpl->setPreviousDecl(PrevFunTmpl); } @@ -2488,7 +2563,7 @@ unsigned FunctionDecl::getBuiltinID() const { // If the function is marked "overloadable", it has a different mangled name // and is not the C library function. - if (getAttr<OverloadableAttr>()) + if (hasAttr<OverloadableAttr>()) return 0; if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) @@ -2510,16 +2585,13 @@ unsigned FunctionDecl::getBuiltinID() const { /// based on its FunctionType. This is the length of the ParamInfo array /// after it has been created. unsigned FunctionDecl::getNumParams() const { - const FunctionType *FT = getType()->castAs<FunctionType>(); - if (isa<FunctionNoProtoType>(FT)) - return 0; - return cast<FunctionProtoType>(FT)->getNumArgs(); - + const FunctionProtoType *FPT = getType()->getAs<FunctionProtoType>(); + return FPT ? FPT->getNumParams() : 0; } void FunctionDecl::setParams(ASTContext &C, ArrayRef<ParmVarDecl *> NewParamInfo) { - assert(ParamInfo == 0 && "Already has param info!"); + assert(!ParamInfo && "Already has param info!"); assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!"); // Zero params -> null pointer. @@ -2536,44 +2608,67 @@ void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) { NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; std::copy(NewDecls.begin(), NewDecls.end(), A); DeclsInPrototypeScope = ArrayRef<NamedDecl *>(A, NewDecls.size()); + // Move declarations introduced in prototype to the function context. + for (auto I : NewDecls) { + DeclContext *DC = I->getDeclContext(); + // Forward-declared reference to an enumeration is not added to + // declaration scope, so skip declaration that is absent from its + // declaration contexts. + if (DC->containsDecl(I)) { + DC->removeDecl(I); + I->setDeclContext(this); + addDecl(I); + } + } } } /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default -/// arguments (in C++) or the last parameter is a parameter pack. +/// arguments (in C++) or are parameter packs (C++11). unsigned FunctionDecl::getMinRequiredArguments() const { if (!getASTContext().getLangOpts().CPlusPlus) return getNumParams(); - - unsigned NumRequiredArgs = getNumParams(); - - // If the last parameter is a parameter pack, we don't need an argument for - // it. - if (NumRequiredArgs > 0 && - getParamDecl(NumRequiredArgs - 1)->isParameterPack()) - --NumRequiredArgs; - - // If this parameter has a default argument, we don't need an argument for - // it. - while (NumRequiredArgs > 0 && - getParamDecl(NumRequiredArgs-1)->hasDefaultArg()) - --NumRequiredArgs; - - // We might have parameter packs before the end. These can't be deduced, - // but they can still handle multiple arguments. - unsigned ArgIdx = NumRequiredArgs; - while (ArgIdx > 0) { - if (getParamDecl(ArgIdx - 1)->isParameterPack()) - NumRequiredArgs = ArgIdx; - - --ArgIdx; - } - + + unsigned NumRequiredArgs = 0; + for (auto *Param : params()) + if (!Param->isParameterPack() && !Param->hasDefaultArg()) + ++NumRequiredArgs; return NumRequiredArgs; } +/// \brief The combination of the extern and inline keywords under MSVC forces +/// the function to be required. +/// +/// Note: This function assumes that we will only get called when isInlined() +/// would return true for this FunctionDecl. +bool FunctionDecl::isMSExternInline() const { + assert(isInlined() && "expected to get called on an inlined function!"); + + const ASTContext &Context = getASTContext(); + if (!Context.getLangOpts().MSVCCompat && !hasAttr<DLLExportAttr>()) + return false; + + for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDecl()) + if (FD->getStorageClass() == SC_Extern) + return true; + + return false; +} + +static bool redeclForcesDefMSVC(const FunctionDecl *Redecl) { + if (Redecl->getStorageClass() != SC_Extern) + return false; + + for (const FunctionDecl *FD = Redecl->getPreviousDecl(); FD; + FD = FD->getPreviousDecl()) + if (FD->getStorageClass() == SC_Extern) + return false; + + return true; +} + static bool RedeclForcesDefC99(const FunctionDecl *Redecl) { // Only consider file-scope declarations in this test. if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) @@ -2593,7 +2688,7 @@ static bool RedeclForcesDefC99(const FunctionDecl *Redecl) { /// \brief For a function declaration in C or C++, determine whether this /// declaration causes the definition to be externally visible. /// -/// Specifically, this determines if adding the current declaration to the set +/// For instance, this determines if adding the current declaration to the set /// of redeclarations of the given functions causes /// isInlineDefinitionExternallyVisible to change from false to true. bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { @@ -2602,6 +2697,13 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { ASTContext &Context = getASTContext(); + if (Context.getLangOpts().MSVCCompat) { + const FunctionDecl *Definition; + if (hasBody(Definition) && Definition->isInlined() && + redeclForcesDefMSVC(this)) + return true; + } + if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) { // With GNU inlining, a declaration with 'inline' but not 'extern', forces // an externally visible definition. @@ -2649,6 +2751,26 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { return FoundBody; } +SourceRange FunctionDecl::getReturnTypeSourceRange() const { + const TypeSourceInfo *TSI = getTypeSourceInfo(); + if (!TSI) + return SourceRange(); + FunctionTypeLoc FTL = + TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>(); + if (!FTL) + return SourceRange(); + + // Skip self-referential return types. + const SourceManager &SM = getASTContext().getSourceManager(); + SourceRange RTRange = FTL.getReturnLoc().getSourceRange(); + SourceLocation Boundary = getNameInfo().getLocStart(); + if (RTRange.isInvalid() || Boundary.isInvalid() || + !SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary)) + return SourceRange(); + + return RTRange; +} + /// \brief For an inline function definition in C, or for a gnu_inline function /// in C++, determine whether the definition will be externally visible. /// @@ -2683,9 +2805,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // If any declaration is 'inline' but not 'extern', then this definition // is externally visible. - for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); - Redecl != RedeclEnd; - ++Redecl) { + for (auto Redecl : redecls()) { if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != SC_Extern) return true; @@ -2702,10 +2822,8 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // [...] If all of the file scope declarations for a function in a // translation unit include the inline function specifier without extern, // then the definition in that translation unit is an inline definition. - for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); - Redecl != RedeclEnd; - ++Redecl) { - if (RedeclForcesDefC99(*Redecl)) + for (auto Redecl : redecls()) { + if (RedeclForcesDefC99(Redecl)) return true; } @@ -2731,7 +2849,7 @@ const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const { if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName) return getDeclName().getCXXLiteralIdentifier(); else - return 0; + return nullptr; } FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { @@ -2753,8 +2871,8 @@ FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) return cast<FunctionDecl>(Info->getInstantiatedFrom()); - - return 0; + + return nullptr; } void @@ -2784,7 +2902,7 @@ bool FunctionDecl::isImplicitlyInstantiable() const { // It is possible to instantiate TSK_ExplicitSpecialization kind // if the FunctionDecl has a class scope specialization pattern. case TSK_ExplicitSpecialization: - return getClassScopeSpecializationPattern() != 0; + return getClassScopeSpecializationPattern() != nullptr; case TSK_ExplicitInstantiationDeclaration: // Handled below. @@ -2824,14 +2942,34 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { // Handle class scope explicit specialization special case. if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) return getClassScopeSpecializationPattern(); - + + // If this is a generic lambda call operator specialization, its + // instantiation pattern is always its primary template's pattern + // even if its primary template was instantiated from another + // member template (which happens with nested generic lambdas). + // Since a lambda's call operator's body is transformed eagerly, + // we don't have to go hunting for a prototype definition template + // (i.e. instantiated-from-member-template) to use as an instantiation + // pattern. + + if (isGenericLambdaCallOperatorSpecialization( + dyn_cast<CXXMethodDecl>(this))) { + assert(getPrimaryTemplate() && "A generic lambda specialization must be " + "generated from a primary call operator " + "template"); + assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() && + "A generic lambda call operator template must always have a body - " + "even if instantiated from a prototype (i.e. as written) member " + "template"); + return getPrimaryTemplate()->getTemplatedDecl(); + } + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { while (Primary->getInstantiatedFromMemberTemplate()) { // If we have hit a point where the user provided a specialization of // this template, we're done looking. if (Primary->isMemberSpecialization()) break; - Primary = Primary->getInstantiatedFromMemberTemplate(); } @@ -2847,7 +2985,7 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->Template.getPointer(); } - return 0; + return nullptr; } FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const { @@ -2861,7 +2999,7 @@ FunctionDecl::getTemplateSpecializationArgs() const { .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->TemplateArguments; } - return 0; + return nullptr; } const ASTTemplateArgumentListInfo * @@ -2871,7 +3009,7 @@ FunctionDecl::getTemplateSpecializationArgsAsWritten() const { .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->TemplateArgumentsAsWritten; } - return 0; + return nullptr; } void @@ -3101,14 +3239,14 @@ FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle) { - return new (C) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo, - BW, Mutable, InitStyle); + return new (C, DC) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo, + BW, Mutable, InitStyle); } FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FieldDecl)); - return new (Mem) FieldDecl(Field, 0, SourceLocation(), SourceLocation(), - 0, QualType(), 0, 0, false, ICIS_NoInit); + return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(), + SourceLocation(), nullptr, QualType(), nullptr, + nullptr, false, ICIS_NoInit); } bool FieldDecl::isAnonymousStructOrUnion() const { @@ -3180,8 +3318,10 @@ TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); } void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { NamedDeclOrQualifier = TDD; - if (TypeForDecl) - assert(TypeForDecl->isLinkageValid()); + if (const Type *T = getTypeForDecl()) { + (void)T; + assert(T->isLinkageValid()); + } assert(isLinkageValid()); } @@ -3189,10 +3329,10 @@ void TagDecl::startDefinition() { IsBeingDefined = true; if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(this)) { - struct CXXRecordDecl::DefinitionData *Data = + struct CXXRecordDecl::DefinitionData *Data = new (getASTContext()) struct CXXRecordDecl::DefinitionData(D); - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) - cast<CXXRecordDecl>(*I)->DefinitionData = Data; + for (auto I : redecls()) + cast<CXXRecordDecl>(I)->DefinitionData = Data; } } @@ -3224,12 +3364,11 @@ TagDecl *TagDecl::getDefinition() const { if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this)) return CXXRD->getDefinition(); - for (redecl_iterator R = redecls_begin(), REnd = redecls_end(); - R != REnd; ++R) + for (auto R : redecls()) if (R->isCompleteDefinition()) - return *R; + return R; - return 0; + return nullptr; } void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { @@ -3244,7 +3383,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { getASTContext().Deallocate(getExtInfo()); - NamedDeclOrQualifier = (TypedefNameDecl*) 0; + NamedDeclOrQualifier = (TypedefNameDecl*)nullptr; } else getExtInfo()->QualifierLoc = QualifierLoc; @@ -3275,21 +3414,28 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed) { - EnumDecl *Enum = new (C) EnumDecl(DC, StartLoc, IdLoc, Id, PrevDecl, - IsScoped, IsScopedUsingClassTag, IsFixed); + EnumDecl *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl, + IsScoped, IsScopedUsingClassTag, + IsFixed); Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules; C.getTypeDeclType(Enum, PrevDecl); return Enum; } EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumDecl)); - EnumDecl *Enum = new (Mem) EnumDecl(0, SourceLocation(), SourceLocation(), - 0, 0, false, false, false); + EnumDecl *Enum = + new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(), + nullptr, nullptr, false, false, false); Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules; return Enum; } +SourceRange EnumDecl::getIntegerTypeRange() const { + if (const TypeSourceInfo *TI = getIntegerTypeSourceInfo()) + return TI->getTypeLoc().getSourceRange(); + return SourceRange(); +} + void EnumDecl::completeDefinition(QualType NewType, QualType NewPromotionType, unsigned NumPositiveBits, @@ -3325,7 +3471,7 @@ EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const { if (SpecializationInfo) return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom()); - return 0; + return nullptr; } void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, @@ -3338,10 +3484,11 @@ void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, // RecordDecl Implementation //===----------------------------------------------------------------------===// -RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, RecordDecl *PrevDecl) - : TagDecl(DK, TK, DC, IdLoc, Id, PrevDecl, StartLoc) { +RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + RecordDecl *PrevDecl) + : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) { HasFlexibleArrayMember = false; AnonymousStructOrUnion = false; HasObjectMember = false; @@ -3353,8 +3500,8 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl* PrevDecl) { - RecordDecl* R = new (C) RecordDecl(Record, TK, DC, StartLoc, IdLoc, Id, - PrevDecl); + RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC, + StartLoc, IdLoc, Id, PrevDecl); R->MayHaveOutOfDateDef = C.getLangOpts().Modules; C.getTypeDeclType(R, PrevDecl); @@ -3362,9 +3509,9 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, } RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(RecordDecl)); - RecordDecl *R = new (Mem) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), - SourceLocation(), 0, 0); + RecordDecl *R = + new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(), + SourceLocation(), nullptr, nullptr); R->MayHaveOutOfDateDef = C.getLangOpts().Modules; return R; } @@ -3427,7 +3574,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { if (Decls.empty()) return; - llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, + std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, /*FieldsAlreadyLoaded=*/false); } @@ -3436,7 +3583,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { //===----------------------------------------------------------------------===// void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { - assert(ParamInfo == 0 && "Already has param info!"); + assert(!ParamInfo && "Already has param info!"); // Zero params -> null pointer. if (!NewParamInfo.empty()) { @@ -3454,7 +3601,7 @@ void BlockDecl::setCaptures(ASTContext &Context, if (begin == end) { NumCaptures = 0; - Captures = 0; + Captures = nullptr; return; } @@ -3469,10 +3616,9 @@ void BlockDecl::setCaptures(ASTContext &Context, } bool BlockDecl::capturesVariable(const VarDecl *variable) const { - for (capture_const_iterator - i = capture_begin(), e = capture_end(); i != e; ++i) + for (const auto &I : captures()) // Only auto vars can be captured, so no redeclaration worries. - if (i->getVariable() == variable) + if (I.getVariable() == variable) return true; return false; @@ -3489,33 +3635,33 @@ SourceRange BlockDecl::getSourceRange() const { void TranslationUnitDecl::anchor() { } TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { - return new (C) TranslationUnitDecl(C); + return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C); } void LabelDecl::anchor() { } LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II) { - return new (C) LabelDecl(DC, IdentL, II, 0, IdentL); + return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, IdentL); } LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, SourceLocation GnuLabelL) { assert(GnuLabelL != IdentL && "Use this only for GNU local labels"); - return new (C) LabelDecl(DC, IdentL, II, 0, GnuLabelL); + return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL); } LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(LabelDecl)); - return new (Mem) LabelDecl(0, SourceLocation(), 0, 0, SourceLocation()); + return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr, + SourceLocation()); } void ValueDecl::anchor() { } bool ValueDecl::isWeak() const { - for (attr_iterator I = attr_begin(), E = attr_end(); I != E; ++I) - if (isa<WeakAttr>(*I) || isa<WeakRefAttr>(*I)) + for (const auto *I : attrs()) + if (isa<WeakAttr>(I) || isa<WeakRefAttr>(I)) return true; return isWeakImported(); @@ -3527,13 +3673,13 @@ ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType Type) { - return new (C) ImplicitParamDecl(DC, IdLoc, Id, Type); + return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type); } -ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, +ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ImplicitParamDecl)); - return new (Mem) ImplicitParamDecl(0, SourceLocation(), 0, QualType()); + return new (C, ID) ImplicitParamDecl(C, nullptr, SourceLocation(), nullptr, + QualType()); } FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, @@ -3541,66 +3687,53 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, - bool isInlineSpecified, + bool isInlineSpecified, bool hasWrittenPrototype, bool isConstexprSpecified) { - FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo, - T, TInfo, SC, - isInlineSpecified, - isConstexprSpecified); + FunctionDecl *New = + new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo, + SC, isInlineSpecified, isConstexprSpecified); New->HasWrittenPrototype = hasWrittenPrototype; return New; } FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionDecl)); - return new (Mem) FunctionDecl(Function, 0, SourceLocation(), - DeclarationNameInfo(), QualType(), 0, - SC_None, false, false); + return new (C, ID) FunctionDecl(Function, C, nullptr, SourceLocation(), + DeclarationNameInfo(), QualType(), nullptr, + SC_None, false, false); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { - return new (C) BlockDecl(DC, L); + return new (C, DC) BlockDecl(DC, L); } BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(BlockDecl)); - return new (Mem) BlockDecl(0, SourceLocation()); -} - -MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(MSPropertyDecl)); - return new (Mem) MSPropertyDecl(0, SourceLocation(), DeclarationName(), - QualType(), 0, SourceLocation(), - 0, 0); + return new (C, ID) BlockDecl(nullptr, SourceLocation()); } CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC, unsigned NumParams) { - unsigned Size = sizeof(CapturedDecl) + NumParams * sizeof(ImplicitParamDecl*); - return new (C.Allocate(Size)) CapturedDecl(DC, NumParams); + return new (C, DC, NumParams * sizeof(ImplicitParamDecl *)) + CapturedDecl(DC, NumParams); } CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID, - unsigned NumParams) { - unsigned Size = sizeof(CapturedDecl) + NumParams * sizeof(ImplicitParamDecl*); - void *Mem = AllocateDeserializedDecl(C, ID, Size); - return new (Mem) CapturedDecl(0, NumParams); + unsigned NumParams) { + return new (C, ID, NumParams * sizeof(ImplicitParamDecl *)) + CapturedDecl(nullptr, NumParams); } EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, const llvm::APSInt &V) { - return new (C) EnumConstantDecl(CD, L, Id, T, E, V); + return new (C, CD) EnumConstantDecl(CD, L, Id, T, E, V); } EnumConstantDecl * EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumConstantDecl)); - return new (Mem) EnumConstantDecl(0, SourceLocation(), 0, QualType(), 0, - llvm::APSInt()); + return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr, + QualType(), nullptr, llvm::APSInt()); } void IndirectFieldDecl::anchor() { } @@ -3609,14 +3742,14 @@ IndirectFieldDecl * IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, NamedDecl **CH, unsigned CHS) { - return new (C) IndirectFieldDecl(DC, L, Id, T, CH, CHS); + return new (C, DC) IndirectFieldDecl(DC, L, Id, T, CH, CHS); } IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(IndirectFieldDecl)); - return new (Mem) IndirectFieldDecl(0, SourceLocation(), DeclarationName(), - QualType(), 0, 0); + return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(), + DeclarationName(), QualType(), nullptr, + 0); } SourceRange EnumConstantDecl::getSourceRange() const { @@ -3631,26 +3764,26 @@ void TypeDecl::anchor() { } TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) { - return new (C) TypedefDecl(DC, StartLoc, IdLoc, Id, TInfo); + return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo); } void TypedefNameDecl::anchor() { } TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypedefDecl)); - return new (Mem) TypedefDecl(0, SourceLocation(), SourceLocation(), 0, 0); + return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(), + nullptr, nullptr); } TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) { - return new (C) TypeAliasDecl(DC, StartLoc, IdLoc, Id, TInfo); + return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo); } TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypeAliasDecl)); - return new (Mem) TypeAliasDecl(0, SourceLocation(), SourceLocation(), 0, 0); + return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(), + SourceLocation(), nullptr, nullptr); } SourceRange TypedefDecl::getSourceRange() const { @@ -3675,24 +3808,23 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, StringLiteral *Str, SourceLocation AsmLoc, SourceLocation RParenLoc) { - return new (C) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc); + return new (C, DC) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc); } -FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, +FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FileScopeAsmDecl)); - return new (Mem) FileScopeAsmDecl(0, 0, SourceLocation(), SourceLocation()); + return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(), + SourceLocation()); } void EmptyDecl::anchor() {} EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { - return new (C) EmptyDecl(DC, L); + return new (C, DC) EmptyDecl(DC, L); } EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EmptyDecl)); - return new (Mem) EmptyDecl(0, SourceLocation()); + return new (C, ID) EmptyDecl(nullptr, SourceLocation()); } //===----------------------------------------------------------------------===// @@ -3730,30 +3862,28 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, *reinterpret_cast<SourceLocation *>(this + 1) = EndLoc; } -ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC, +ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, Module *Imported, ArrayRef<SourceLocation> IdentifierLocs) { - void *Mem = C.Allocate(sizeof(ImportDecl) + - IdentifierLocs.size() * sizeof(SourceLocation)); - return new (Mem) ImportDecl(DC, StartLoc, Imported, IdentifierLocs); + return new (C, DC, IdentifierLocs.size() * sizeof(SourceLocation)) + ImportDecl(DC, StartLoc, Imported, IdentifierLocs); } -ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, +ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - Module *Imported, + Module *Imported, SourceLocation EndLoc) { - void *Mem = C.Allocate(sizeof(ImportDecl) + sizeof(SourceLocation)); - ImportDecl *Import = new (Mem) ImportDecl(DC, StartLoc, Imported, EndLoc); + ImportDecl *Import = + new (C, DC, sizeof(SourceLocation)) ImportDecl(DC, StartLoc, + Imported, EndLoc); Import->setImplicit(); return Import; } ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumLocations) { - void *Mem = AllocateDeserializedDecl(C, ID, - (sizeof(ImportDecl) + - NumLocations * sizeof(SourceLocation))); - return new (Mem) ImportDecl(EmptyShell()); + return new (C, ID, NumLocations * sizeof(SourceLocation)) + ImportDecl(EmptyShell()); } ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const { diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index 121c5a6..2b1506d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -45,25 +45,30 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const { getASTContext().getExternalSource()->updateOutOfDateIdentifier(II); } -void *Decl::AllocateDeserializedDecl(const ASTContext &Context, - unsigned ID, - unsigned Size) { +void *Decl::operator new(std::size_t Size, const ASTContext &Context, + unsigned ID, std::size_t Extra) { // Allocate an extra 8 bytes worth of storage, which ensures that the // resulting pointer will still be 8-byte aligned. - void *Start = Context.Allocate(Size + 8); + void *Start = Context.Allocate(Size + Extra + 8); void *Result = (char*)Start + 8; - + unsigned *PrefixPtr = (unsigned *)Result - 2; - + // Zero out the first 4 bytes; this is used to store the owning module ID. PrefixPtr[0] = 0; - + // Store the global declaration ID in the second 4 bytes. PrefixPtr[1] = ID; - + return Result; } +void *Decl::operator new(std::size_t Size, const ASTContext &Ctx, + DeclContext *Parent, std::size_t Extra) { + assert(!Parent || &Parent->getParentASTContext() == &Ctx); + return ::operator new(Size + Extra, Ctx); +} + Module *Decl::getOwningModuleSlow() const { assert(isFromASTFile() && "Not from AST file?"); return getASTContext().getExternalSource()->getModule(getOwningModuleID()); @@ -80,6 +85,7 @@ const char *Decl::getDeclKindName() const { void Decl::setInvalidDecl(bool Invalid) { InvalidDecl = Invalid; + assert(!isa<TagDecl>(this) || !cast<TagDecl>(this)->isCompleteDefinition()); if (Invalid && !isa<ParmVarDecl>(this)) { // Defensive maneuver for ill-formed code: we're likely not to make it to // a point where we set the access specifier, so default it to "public" @@ -153,11 +159,12 @@ bool Decl::isParameterPack() const { return isTemplateParameterPack(); } -bool Decl::isFunctionOrFunctionTemplate() const { - if (const UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(this)) - return UD->getTargetDecl()->isFunctionOrFunctionTemplate(); - - return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this); +FunctionDecl *Decl::getAsFunction() { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) + return FD; + if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(this)) + return FTD->getTemplatedDecl(); + return nullptr; } bool Decl::isTemplateDecl() const { @@ -171,7 +178,7 @@ const DeclContext *Decl::getParentFunctionOrMethod() const { if (DC->isFunctionOrMethod()) return DC; - return 0; + return nullptr; } @@ -244,6 +251,10 @@ bool Decl::isInAnonymousNamespace() const { return false; } +bool Decl::isInStdNamespace() const { + return getDeclContext()->isStdNamespace(); +} + TranslationUnitDecl *Decl::getTranslationUnitDecl() { if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this)) return TUD; @@ -306,7 +317,7 @@ bool Decl::isReferenced() const { return true; // Check redeclarations. - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) + for (auto I : redecls()) if (I->Referenced) return true; @@ -401,8 +412,8 @@ AvailabilityResult Decl::getAvailability(std::string *Message) const { AvailabilityResult Result = AR_Available; std::string ResultMessage; - for (attr_iterator A = attr_begin(), AEnd = attr_end(); A != AEnd; ++A) { - if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(*A)) { + for (const auto *A : attrs()) { + if (const auto *Deprecated = dyn_cast<DeprecatedAttr>(A)) { if (Result >= AR_Deprecated) continue; @@ -413,13 +424,13 @@ AvailabilityResult Decl::getAvailability(std::string *Message) const { continue; } - if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(*A)) { + if (const auto *Unavailable = dyn_cast<UnavailableAttr>(A)) { if (Message) *Message = Unavailable->getMessage(); return AR_Unavailable; } - if (AvailabilityAttr *Availability = dyn_cast<AvailabilityAttr>(*A)) { + if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { AvailabilityResult AR = CheckAvailability(getASTContext(), Availability, Message); @@ -475,13 +486,13 @@ bool Decl::isWeakImported() const { if (!canBeWeakImported(IsDefinition)) return false; - for (attr_iterator A = attr_begin(), AEnd = attr_end(); A != AEnd; ++A) { - if (isa<WeakImportAttr>(*A)) + for (const auto *A : attrs()) { + if (isa<WeakImportAttr>(A)) return true; - if (AvailabilityAttr *Availability = dyn_cast<AvailabilityAttr>(*A)) { - if (CheckAvailability(getASTContext(), Availability, 0) - == AR_NotYetIntroduced) + if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { + if (CheckAvailability(getASTContext(), Availability, + nullptr) == AR_NotYetIntroduced) return true; } } @@ -662,7 +673,7 @@ SourceLocation Decl::getBodyRBrace() const { return SourceLocation(); } -void Decl::CheckAccessDeclContext() const { +bool Decl::AccessDeclContextSanity() const { #ifndef NDEBUG // Suppress this check if any of the following hold: // 1. this is the translation unit (and thus has no parent) @@ -684,16 +695,35 @@ void Decl::CheckAccessDeclContext() const { // AS_none as access specifier. isa<CXXRecordDecl>(this) || isa<ClassScopeFunctionSpecializationDecl>(this)) - return; + return true; assert(Access != AS_none && "Access specifier is AS_none inside a record decl"); #endif + return true; } static Decl::Kind getKind(const Decl *D) { return D->getKind(); } static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); } +const FunctionType *Decl::getFunctionType(bool BlocksToo) const { + QualType Ty; + if (const ValueDecl *D = dyn_cast<ValueDecl>(this)) + Ty = D->getType(); + else if (const TypedefNameDecl *D = dyn_cast<TypedefNameDecl>(this)) + Ty = D->getUnderlyingType(); + else + return nullptr; + + if (Ty->isFunctionPointerType()) + Ty = Ty->getAs<PointerType>()->getPointeeType(); + else if (BlocksToo && Ty->isBlockPointerType()) + Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); + + return Ty->getAs<FunctionType>(); +} + + /// Starting at a given context (a Decl or DeclContext), look for a /// code context that is not a closure (a lambda, block, etc.). template <class T> static Decl *getNonClosureContext(T *D) { @@ -712,7 +742,7 @@ template <class T> static Decl *getNonClosureContext(T *D) { } else if (CapturedDecl *CD = dyn_cast<CapturedDecl>(D)) { return getNonClosureContext(CD->getParent()); } else { - return 0; + return nullptr; } } @@ -769,6 +799,22 @@ bool DeclContext::isInlineNamespace() const { cast<NamespaceDecl>(this)->isInline(); } +bool DeclContext::isStdNamespace() const { + if (!isNamespace()) + return false; + + const NamespaceDecl *ND = cast<NamespaceDecl>(this); + if (ND->isInline()) { + return ND->getParent()->isStdNamespace(); + } + + if (!getParent()->getRedeclContext()->isTranslationUnit()) + return false; + + const IdentifierInfo *II = ND->getIdentifier(); + return II && II->isStr("std"); +} + bool DeclContext::isDependentContext() const { if (isFileContext()) return false; @@ -811,7 +857,7 @@ static bool isLinkageSpecContext(const DeclContext *DC, while (DC->getDeclKind() != Decl::TranslationUnit) { if (DC->getDeclKind() == Decl::LinkageSpec) return cast<LinkageSpecDecl>(DC)->getLanguage() == ID; - DC = DC->getParent(); + DC = DC->getLexicalParent(); } return false; } @@ -874,18 +920,17 @@ DeclContext *DeclContext::getPrimaryContext() { // If this is a tag type that has a definition or is currently // being defined, that definition is our primary context. TagDecl *Tag = cast<TagDecl>(this); - assert(isa<TagType>(Tag->TypeForDecl) || - isa<InjectedClassNameType>(Tag->TypeForDecl)); if (TagDecl *Def = Tag->getDefinition()) return Def; - if (!isa<InjectedClassNameType>(Tag->TypeForDecl)) { - const TagType *TagTy = cast<TagType>(Tag->TypeForDecl); - if (TagTy->isBeingDefined()) - // FIXME: is it necessarily being defined in the decl - // that owns the type? - return TagTy->getDecl(); + if (const TagType *TagTy = dyn_cast<TagType>(Tag->getTypeForDecl())) { + // Note, TagType::getDecl returns the (partial) definition one exists. + TagDecl *PossiblePartialDef = TagTy->getDecl(); + if (PossiblePartialDef->isBeingDefined()) + return PossiblePartialDef; + } else { + assert(isa<InjectedClassNameType>(Tag->getTypeForDecl())); } return Tag; @@ -918,8 +963,8 @@ std::pair<Decl *, Decl *> DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded) { // Build up a chain of declarations via the Decl::NextInContextAndBits field. - Decl *FirstNewDecl = 0; - Decl *PrevDecl = 0; + Decl *FirstNewDecl = nullptr; + Decl *PrevDecl = nullptr; for (unsigned I = 0, N = Decls.size(); I != N; ++I) { if (FieldsAlreadyLoaded && isa<FieldDecl>(Decls[I])) continue; @@ -939,13 +984,12 @@ DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls, /// \brief We have just acquired external visible storage, and we already have /// built a lookup map. For every name in the map, pull in the new names from /// the external storage. -void DeclContext::reconcileExternalVisibleStorage() { +void DeclContext::reconcileExternalVisibleStorage() const { assert(NeedToReconcileExternalVisibleStorage && LookupPtr.getPointer()); NeedToReconcileExternalVisibleStorage = false; - StoredDeclsMap &Map = *LookupPtr.getPointer(); - for (StoredDeclsMap::iterator I = Map.begin(); I != Map.end(); ++I) - I->second.setHasExternalDecls(); + for (auto &Lookup : *LookupPtr.getPointer()) + Lookup.second.setHasExternalDecls(); } /// \brief Load the declarations within this lexical storage from an @@ -982,8 +1026,8 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { // Splice the newly-read declarations into the beginning of the list // of declarations. Decl *ExternalFirst, *ExternalLast; - llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls, - FieldsAlreadyLoaded); + std::tie(ExternalFirst, ExternalLast) = + BuildDeclChain(Decls, FieldsAlreadyLoaded); ExternalLast->NextInContextAndBits.setPointer(FirstDecl); FirstDecl = ExternalFirst; if (!LastDecl) @@ -997,6 +1041,8 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, StoredDeclsMap *Map; if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); + if (DC->NeedToReconcileExternalVisibleStorage) + DC->reconcileExternalVisibleStorage(); (*Map)[Name].removeExternalDecls(); @@ -1011,6 +1057,8 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, StoredDeclsMap *Map; if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); + if (DC->NeedToReconcileExternalVisibleStorage) + DC->reconcileExternalVisibleStorage(); StoredDeclsList &List = (*Map)[Name]; @@ -1050,14 +1098,9 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, return List.getLookupResult(); } -DeclContext::decl_iterator DeclContext::noload_decls_begin() const { - return decl_iterator(FirstDecl); -} - DeclContext::decl_iterator DeclContext::decls_begin() const { if (hasExternalLexicalStorage()) LoadLexicalDeclsFromExternalStorage(); - return decl_iterator(FirstDecl); } @@ -1082,7 +1125,7 @@ void DeclContext::removeDecl(Decl *D) { // Remove D from the decl chain. This is O(n) but hopefully rare. if (D == FirstDecl) { if (D == LastDecl) - FirstDecl = LastDecl = 0; + FirstDecl = LastDecl = nullptr; else FirstDecl = D->NextInContextAndBits.getPointer(); } else { @@ -1097,7 +1140,7 @@ void DeclContext::removeDecl(Decl *D) { } // Mark that D is no longer in the decl chain. - D->NextInContextAndBits.setPointer(0); + D->NextInContextAndBits.setPointer(nullptr); // Remove D from the lookup table if necessary. if (isa<NamedDecl>(D)) { @@ -1187,6 +1230,10 @@ static bool shouldBeHidden(NamedDecl *D) { /// buildLookup - Build the lookup data structure with all of the /// declarations in this DeclContext (and any other contexts linked /// to it or transparent contexts nested within it) and return it. +/// +/// Note that the produced map may miss out declarations from an +/// external source. If it does, those entries will be marked with +/// the 'hasExternalDecls' flag. StoredDeclsMap *DeclContext::buildLookup() { assert(this == getPrimaryContext() && "buildLookup called on non-primary DC"); @@ -1202,7 +1249,6 @@ StoredDeclsMap *DeclContext::buildLookup() { // We no longer have any lazy decls. LookupPtr.setInt(false); - NeedToReconcileExternalVisibleStorage = false; return LookupPtr.getPointer(); } @@ -1251,11 +1297,13 @@ DeclContext::lookup(DeclarationName Name) { return PrimaryContext->lookup(Name); if (hasExternalVisibleStorage()) { + if (NeedToReconcileExternalVisibleStorage) + reconcileExternalVisibleStorage(); + StoredDeclsMap *Map = LookupPtr.getPointer(); + if (LookupPtr.getInt()) Map = buildLookup(); - else if (NeedToReconcileExternalVisibleStorage) - reconcileExternalVisibleStorage(); if (!Map) Map = CreateStoredDeclsMap(getParentASTContext()); @@ -1267,7 +1315,7 @@ DeclContext::lookup(DeclarationName Name) { return R.first->second.getLookupResult(); ExternalASTSource *Source = getParentASTContext().getExternalSource(); - if (Source->FindExternalVisibleDeclsByName(this, Name) || R.second) { + if (Source->FindExternalVisibleDeclsByName(this, Name) || !R.second) { if (StoredDeclsMap *Map = LookupPtr.getPointer()) { StoredDeclsMap::iterator I = Map->find(Name); if (I != Map->end()) @@ -1275,7 +1323,7 @@ DeclContext::lookup(DeclarationName Name) { } } - return lookup_result(lookup_iterator(0), lookup_iterator(0)); + return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); } StoredDeclsMap *Map = LookupPtr.getPointer(); @@ -1283,11 +1331,11 @@ DeclContext::lookup(DeclarationName Name) { Map = buildLookup(); if (!Map) - return lookup_result(lookup_iterator(0), lookup_iterator(0)); + return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); StoredDeclsMap::iterator I = Map->find(Name); if (I == Map->end()) - return lookup_result(lookup_iterator(0), lookup_iterator(0)); + return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); return I->second.getLookupResult(); } @@ -1324,12 +1372,12 @@ DeclContext::noload_lookup(DeclarationName Name) { } if (!Map) - return lookup_result(lookup_iterator(0), lookup_iterator(0)); + return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); StoredDeclsMap::iterator I = Map->find(Name); - return I != Map->end() - ? I->second.getLookupResult() - : lookup_result(lookup_iterator(0), lookup_iterator(0)); + return I != Map->end() ? I->second.getLookupResult() + : lookup_result(lookup_iterator(nullptr), + lookup_iterator(nullptr)); } void DeclContext::localUncachedLookup(DeclarationName Name, @@ -1502,13 +1550,13 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) { /// Returns iterator range [First, Last) of UsingDirectiveDecls stored within /// this context. -DeclContext::udir_iterator_range -DeclContext::getUsingDirectives() const { +DeclContext::udir_range DeclContext::using_directives() const { // FIXME: Use something more efficient than normal lookup for using // directives. In C++, using directives are looked up more than anything else. lookup_const_result Result = lookup(UsingDirectiveDecl::getName()); - return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.begin()), - reinterpret_cast<udir_iterator>(Result.end())); + return udir_range( + reinterpret_cast<UsingDirectiveDecl *const *>(Result.begin()), + reinterpret_cast<UsingDirectiveDecl *const *>(Result.end())); } //===----------------------------------------------------------------------===// @@ -1568,7 +1616,7 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C, // Allocate the copy of the PartialDiagnostic via the ASTContext's // BumpPtrAllocator, rather than the ASTContext itself. - PartialDiagnostic::Storage *DiagStorage = 0; + PartialDiagnostic::Storage *DiagStorage = nullptr; if (PDiag.hasStorage()) DiagStorage = new (C) PartialDiagnostic::Storage; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index a17abdd..ed26c52 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -31,8 +31,7 @@ using namespace clang; void AccessSpecDecl::anchor() { } AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(AccessSpecDecl)); - return new (Mem) AccessSpecDecl(EmptyShell()); + return new (C, ID) AccessSpecDecl(EmptyShell()); } void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const { @@ -51,7 +50,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), - HasMutableFields(false), HasOnlyCMembers(true), + HasMutableFields(false), HasVariantMembers(false), HasOnlyCMembers(true), HasInClassInitializer(false), HasUninitializedReferenceMember(false), NeedOverloadResolutionForMoveConstructor(false), NeedOverloadResolutionForMoveAssignment(false), @@ -71,7 +70,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), - IsLambda(false), NumBases(0), NumVBases(0), Bases(), VBases(), + IsLambda(false), IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), + Bases(), VBases(), Definition(D), FirstFriend() { } @@ -83,20 +83,22 @@ CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getVBasesSlowCase() const { return VBases.get(Definition->getASTContext().getExternalSource()); } -CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, CXXRecordDecl *PrevDecl) - : RecordDecl(K, TK, DC, StartLoc, IdLoc, Id, PrevDecl), - DefinitionData(PrevDecl ? PrevDecl->DefinitionData : 0), - TemplateOrInstantiation() { } +CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + CXXRecordDecl *PrevDecl) + : RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl), + DefinitionData(PrevDecl ? PrevDecl->DefinitionData + : DefinitionDataPtr(this)), + TemplateOrInstantiation() {} CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl* PrevDecl, bool DelayTypeCreation) { - CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, StartLoc, IdLoc, - Id, PrevDecl); + CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, + IdLoc, Id, PrevDecl); R->MayHaveOutOfDateDef = C.getLangOpts().Modules; // FIXME: DelayTypeCreation seems like such a hack @@ -105,29 +107,29 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, return R; } -CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, - TypeSourceInfo *Info, SourceLocation Loc, - bool Dependent, bool IsGeneric, - LambdaCaptureDefault CaptureDefault) { - CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, - 0, 0); +CXXRecordDecl * +CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, + TypeSourceInfo *Info, SourceLocation Loc, + bool Dependent, bool IsGeneric, + LambdaCaptureDefault CaptureDefault) { + CXXRecordDecl *R = + new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc, + nullptr, nullptr); R->IsBeingDefined = true; - R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, - Dependent, - IsGeneric, - CaptureDefault); + R->DefinitionData = + new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric, + CaptureDefault); R->MayHaveOutOfDateDef = false; R->setImplicit(true); - C.getTypeDeclType(R, /*PrevDecl=*/0); + C.getTypeDeclType(R, /*PrevDecl=*/nullptr); return R; } CXXRecordDecl * CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXRecordDecl)); - CXXRecordDecl *R = new (Mem) CXXRecordDecl(CXXRecord, TTK_Struct, 0, - SourceLocation(), SourceLocation(), - 0, 0); + CXXRecordDecl *R = new (C, ID) CXXRecordDecl( + CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(), + nullptr, nullptr); R->MayHaveOutOfDateDef = false; return R; } @@ -205,19 +207,17 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().HasNonLiteralTypeFieldsOrBases = true; // Now go through all virtual bases of this base and add them. - for (CXXRecordDecl::base_class_iterator VBase = - BaseClassDecl->vbases_begin(), - E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) { + for (const auto &VBase : BaseClassDecl->vbases()) { // Add this base if it's not already in the list. - if (SeenVBaseTypes.insert(C.getCanonicalType(VBase->getType()))) { - VBases.push_back(VBase); + if (SeenVBaseTypes.insert(C.getCanonicalType(VBase.getType()))) { + VBases.push_back(&VBase); // C++11 [class.copy]p8: // The implicitly-declared copy constructor for a class X will have // the form 'X::X(const X&)' if each [...] virtual base class B of X // has a copy constructor whose first parameter is of type // 'const B&' or 'const volatile B&' [...] - if (CXXRecordDecl *VBaseDecl = VBase->getType()->getAsCXXRecordDecl()) + if (CXXRecordDecl *VBaseDecl = VBase.getType()->getAsCXXRecordDecl()) if (!VBaseDecl->hasCopyConstructorWithConstParam()) data().ImplicitCopyConstructorHasConstParam = false; } @@ -335,8 +335,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, addedClassSubobject(BaseClassDecl); } - if (VBases.empty()) + if (VBases.empty()) { + data().IsParsingBaseSpecifiers = false; return; + } // Create base specifier for any direct or indirect virtual bases. data().VBases = new (C) CXXBaseSpecifier[VBases.size()]; @@ -347,6 +349,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, addedClassSubobject(Type->getAsCXXRecordDecl()); data().getVBases()[I] = *VBases[I]; } + + data().IsParsingBaseSpecifiers = false; } void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { @@ -391,7 +395,7 @@ bool CXXRecordDecl::hasAnyDependentBases() const { if (!isDependentContext()) return false; - return !forallBases(SawBase, 0); + return !forallBases(SawBase, nullptr); } bool CXXRecordDecl::isTriviallyCopyable() const { @@ -532,8 +536,11 @@ void CXXRecordDecl::addedMember(Decl *D) { if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) { SMKind |= SMF_Destructor; - if (!DD->isImplicit()) + if (DD->isUserProvided()) data().HasIrrelevantDestructor = false; + // If the destructor is explicitly defaulted and not trivial or not public + // or if the destructor is deleted, we clear HasIrrelevantDestructor in + // finishedDefaultedOrDeletedMember. // C++11 [class.dtor]p5: // A destructor is trivial if [...] the destructor is not virtual. @@ -656,7 +663,13 @@ void CXXRecordDecl::addedMember(Decl *D) { // Keep track of the presence of mutable fields. if (Field->isMutable()) data().HasMutableFields = true; - + + // C++11 [class.union]p8, DR1460: + // If X is a union, a non-static data member of X that is not an anonymous + // union is a variant member of X. + if (isUnion() && !Field->isAnonymousStructOrUnion()) + data().HasVariantMembers = true; + // C++0x [class]p9: // A POD struct is a class that is both a trivial class and a // standard-layout class, and has no non-static data members of type @@ -692,7 +705,9 @@ void CXXRecordDecl::addedMember(Decl *D) { if (!T->isLiteralType(Context) || T.isVolatileQualified()) data().HasNonLiteralTypeFieldsOrBases = true; - if (Field->hasInClassInitializer()) { + if (Field->hasInClassInitializer() || + (Field->isAnonymousStructOrUnion() && + Field->getType()->getAsCXXRecordDecl()->hasInClassInitializer())) { data().HasInClassInitializer = true; // C++11 [class]p5: @@ -809,15 +824,13 @@ void CXXRecordDecl::addedMember(Decl *D) { // Virtual bases and virtual methods make a class non-empty, but they // also make it non-standard-layout so we needn't check here. // A non-empty base class may leave the class standard-layout, but not - // if we have arrived here, and have at least on non-static data + // if we have arrived here, and have at least one non-static data // member. If IsStandardLayout remains true, then the first non-static // data member must come through here with Empty still true, and Empty // will subsequently be set to false below. if (data().IsStandardLayout && data().Empty) { - for (CXXRecordDecl::base_class_const_iterator BI = bases_begin(), - BE = bases_end(); - BI != BE; ++BI) { - if (Context.hasSameUnqualifiedType(BI->getType(), T)) { + for (const auto &BI : bases()) { + if (Context.hasSameUnqualifiedType(BI.getType(), T)) { data().IsStandardLayout = false; break; } @@ -862,6 +875,13 @@ void CXXRecordDecl::addedMember(Decl *D) { if (FieldRec->hasUninitializedReferenceMember() && !Field->hasInClassInitializer()) data().HasUninitializedReferenceMember = true; + + // C++11 [class.union]p8, DR1460: + // a non-static data member of an anonymous union that is a member of + // X is also a variant member of X. + if (FieldRec->hasVariantMembers() && + Field->isAnonymousStructOrUnion()) + data().HasVariantMembers = true; } } else { // Base element type of field is a non-class type. @@ -928,9 +948,11 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { else if (Constructor->isConstexpr()) // We may now know that the constructor is constexpr. data().HasConstexprNonCopyMoveConstructor = true; - } else if (isa<CXXDestructorDecl>(D)) + } else if (isa<CXXDestructorDecl>(D)) { SMKind |= SMF_Destructor; - else if (D->isCopyAssignmentOperator()) + if (!D->isTrivial() || D->getAccess() != AS_public || D->isDeleted()) + data().HasIrrelevantDestructor = false; + } else if (D->isCopyAssignmentOperator()) SMKind |= SMF_CopyAssignment; else if (D->isMoveAssignmentOperator()) SMKind |= SMF_MoveAssignment; @@ -959,7 +981,7 @@ bool CXXRecordDecl::isGenericLambda() const { } CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const { - if (!isLambda()) return 0; + if (!isLambda()) return nullptr; DeclarationName Name = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); DeclContext::lookup_const_result Calls = lookup(Name); @@ -976,11 +998,11 @@ CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const { } CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const { - if (!isLambda()) return 0; + if (!isLambda()) return nullptr; DeclarationName Name = &getASTContext().Idents.get(getLambdaStaticInvokerName()); DeclContext::lookup_const_result Invoker = lookup(Name); - if (Invoker.empty()) return 0; + if (Invoker.empty()) return nullptr; assert(Invoker.size() == 1 && "More than one static invoker operator!"); NamedDecl *InvokerFun = Invoker.front(); if (FunctionTemplateDecl *InvokerTemplate = @@ -994,11 +1016,11 @@ void CXXRecordDecl::getCaptureFields( llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, FieldDecl *&ThisCapture) const { Captures.clear(); - ThisCapture = 0; + ThisCapture = nullptr; LambdaDefinitionData &Lambda = getLambdaData(); RecordDecl::field_iterator Field = field_begin(); - for (LambdaExpr::Capture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures; + for (const LambdaCapture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures; C != CEnd; ++C, ++Field) { if (C->capturesThis()) ThisCapture = *Field; @@ -1010,21 +1032,17 @@ void CXXRecordDecl::getCaptureFields( TemplateParameterList * CXXRecordDecl::getGenericLambdaTemplateParameterList() const { - if (!isLambda()) return 0; + if (!isLambda()) return nullptr; CXXMethodDecl *CallOp = getLambdaCallOperator(); if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate()) return Tmpl->getTemplateParameters(); - return 0; + return nullptr; } static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { - QualType T; - if (isa<UsingShadowDecl>(Conv)) - Conv = cast<UsingShadowDecl>(Conv)->getTargetDecl(); - if (FunctionTemplateDecl *ConvTemp = dyn_cast<FunctionTemplateDecl>(Conv)) - T = ConvTemp->getTemplatedDecl()->getResultType(); - else - T = cast<CXXConversionDecl>(Conv)->getConversionType(); + QualType T = + cast<CXXConversionDecl>(Conv->getUnderlyingDecl()->getAsFunction()) + ->getConversionType(); return Context.getCanonicalType(T); } @@ -1087,14 +1105,13 @@ static void CollectVisibleConversions(ASTContext &Context, } // Collect information recursively from any base classes. - for (CXXRecordDecl::base_class_iterator - I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { - const RecordType *RT = I->getType()->getAs<RecordType>(); + for (const auto &I : Record->bases()) { + const RecordType *RT = I.getType()->getAs<RecordType>(); if (!RT) continue; AccessSpecifier BaseAccess - = CXXRecordDecl::MergeAccess(Access, I->getAccessSpecifier()); - bool BaseInVirtual = InVirtual || I->isVirtual(); + = CXXRecordDecl::MergeAccess(Access, I.getAccessSpecifier()); + bool BaseInVirtual = InVirtual || I.isVirtual(); CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl()); CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess, @@ -1130,13 +1147,12 @@ static void CollectVisibleConversions(ASTContext &Context, HiddenTypes.insert(GetConversionType(Context, ConvI.getDecl())); // Recursively collect conversions from base classes. - for (CXXRecordDecl::base_class_iterator - I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { - const RecordType *RT = I->getType()->getAs<RecordType>(); + for (const auto &I : Record->bases()) { + const RecordType *RT = I.getType()->getAs<RecordType>(); if (!RT) continue; CollectVisibleConversions(Context, cast<CXXRecordDecl>(RT->getDecl()), - I->isVirtual(), I->getAccessSpecifier(), + I.isVirtual(), I.getAccessSpecifier(), HiddenTypes, Output, VBaseCs, HiddenVBaseCs); } @@ -1197,8 +1213,8 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const { if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom()); - - return 0; + + return nullptr; } void @@ -1248,14 +1264,14 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { DeclContext::lookup_const_result R = lookup(Name); if (R.empty()) - return 0; + return nullptr; CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(R.front()); return Dtor; } void CXXRecordDecl::completeDefinition() { - completeDefinition(0); + completeDefinition(nullptr); } void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { @@ -1317,11 +1333,9 @@ bool CXXRecordDecl::mayBeAbstract() const { isDependentContext()) return false; - for (CXXRecordDecl::base_class_const_iterator B = bases_begin(), - BEnd = bases_end(); - B != BEnd; ++B) { + for (const auto &B : bases()) { CXXRecordDecl *BaseDecl - = cast<CXXRecordDecl>(B->getType()->getAs<RecordType>()->getDecl()); + = cast<CXXRecordDecl>(B.getType()->getAs<RecordType>()->getDecl()); if (BaseDecl->isAbstract()) return true; } @@ -1369,7 +1383,7 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, if (MayBeBase && recursivelyOverrides(this, MD)) return MD; } - return NULL; + return nullptr; } lookup_const_result Candidates = RD->lookup(getDeclName()); @@ -1383,9 +1397,8 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, return MD; } - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - const RecordType *RT = I->getType()->getAs<RecordType>(); + for (const auto &I : RD->bases()) { + const RecordType *RT = I.getType()->getAs<RecordType>(); if (!RT) continue; const CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl()); @@ -1394,7 +1407,7 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, return T; } - return NULL; + return nullptr; } CXXMethodDecl * @@ -1404,17 +1417,15 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInline, bool isConstexpr, SourceLocation EndLocation) { - return new (C) CXXMethodDecl(CXXMethod, RD, StartLoc, NameInfo, T, TInfo, - SC, isInline, isConstexpr, - EndLocation); + return new (C, RD) CXXMethodDecl(CXXMethod, C, RD, StartLoc, NameInfo, + T, TInfo, SC, isInline, isConstexpr, + EndLocation); } CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXMethodDecl)); - return new (Mem) CXXMethodDecl(CXXMethod, 0, SourceLocation(), - DeclarationNameInfo(), QualType(), - 0, SC_None, false, false, - SourceLocation()); + return new (C, ID) CXXMethodDecl(CXXMethod, C, nullptr, SourceLocation(), + DeclarationNameInfo(), QualType(), nullptr, + SC_None, false, false, SourceLocation()); } bool CXXMethodDecl::isUsualDeallocationFunction() const { @@ -1511,12 +1522,12 @@ void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) { } CXXMethodDecl::method_iterator CXXMethodDecl::begin_overridden_methods() const { - if (isa<CXXConstructorDecl>(this)) return 0; + if (isa<CXXConstructorDecl>(this)) return nullptr; return getASTContext().overridden_methods_begin(this); } CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const { - if (isa<CXXConstructorDecl>(this)) return 0; + if (isa<CXXConstructorDecl>(this)) return nullptr; return getASTContext().overridden_methods_end(this); } @@ -1614,7 +1625,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, VarDecl **Indices, unsigned NumIndices) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsVirtual(false), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) { VarDecl **MyIndices = reinterpret_cast<VarDecl **> (this + 1); @@ -1646,7 +1657,7 @@ const Type *CXXCtorInitializer::getBaseClass() const { if (isBaseInitializer()) return Initializee.get<TypeSourceInfo*>()->getType().getTypePtr(); else - return 0; + return nullptr; } SourceLocation CXXCtorInitializer::getSourceLocation() const { @@ -1677,9 +1688,9 @@ void CXXConstructorDecl::anchor() { } CXXConstructorDecl * CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXConstructorDecl)); - return new (Mem) CXXConstructorDecl(0, SourceLocation(),DeclarationNameInfo(), - QualType(), 0, false, false, false,false); + return new (C, ID) CXXConstructorDecl(C, nullptr, SourceLocation(), + DeclarationNameInfo(), QualType(), + nullptr, false, false, false, false); } CXXConstructorDecl * @@ -1692,9 +1703,9 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); - return new (C) CXXConstructorDecl(RD, StartLoc, NameInfo, T, TInfo, - isExplicit, isInline, isImplicitlyDeclared, - isConstexpr); + return new (C, RD) CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, + isExplicit, isInline, + isImplicitlyDeclared, isConstexpr); } CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const { @@ -1702,8 +1713,8 @@ CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const { Expr *E = (*init_begin())->getInit()->IgnoreImplicit(); if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(E)) return Construct->getConstructor(); - - return 0; + + return nullptr; } bool CXXConstructorDecl::isDefaultConstructor() const { @@ -1739,8 +1750,8 @@ bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const { // all other parameters have default arguments. if ((getNumParams() < 1) || (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || - (getPrimaryTemplate() != 0) || - (getDescribedFunctionTemplate() != 0)) + (getPrimaryTemplate() != nullptr) || + (getDescribedFunctionTemplate() != nullptr)) return false; const ParmVarDecl *Param = getParamDecl(0); @@ -1788,8 +1799,8 @@ bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const { bool CXXConstructorDecl::isSpecializationCopyingObject() const { if ((getNumParams() < 1) || (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || - (getPrimaryTemplate() == 0) || - (getDescribedFunctionTemplate() != 0)) + (getPrimaryTemplate() == nullptr) || + (getDescribedFunctionTemplate() != nullptr)) return false; const ParmVarDecl *Param = getParamDecl(0); @@ -1810,7 +1821,7 @@ const CXXConstructorDecl *CXXConstructorDecl::getInheritedConstructor() const { // Hack: we store the inherited constructor in the overridden method table method_iterator It = getASTContext().overridden_methods_begin(this); if (It == getASTContext().overridden_methods_end(this)) - return 0; + return nullptr; return cast<CXXConstructorDecl>(*It); } @@ -1827,9 +1838,9 @@ void CXXDestructorDecl::anchor() { } CXXDestructorDecl * CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXDestructorDecl)); - return new (Mem) CXXDestructorDecl(0, SourceLocation(), DeclarationNameInfo(), - QualType(), 0, false, false); + return new (C, ID) + CXXDestructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(), + QualType(), nullptr, false, false); } CXXDestructorDecl * @@ -1841,18 +1852,18 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, assert(NameInfo.getName().getNameKind() == DeclarationName::CXXDestructorName && "Name must refer to a destructor"); - return new (C) CXXDestructorDecl(RD, StartLoc, NameInfo, T, TInfo, isInline, - isImplicitlyDeclared); + return new (C, RD) CXXDestructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, + isInline, isImplicitlyDeclared); } void CXXConversionDecl::anchor() { } CXXConversionDecl * CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXConversionDecl)); - return new (Mem) CXXConversionDecl(0, SourceLocation(), DeclarationNameInfo(), - QualType(), 0, false, false, false, - SourceLocation()); + return new (C, ID) CXXConversionDecl(C, nullptr, SourceLocation(), + DeclarationNameInfo(), QualType(), + nullptr, false, false, false, + SourceLocation()); } CXXConversionDecl * @@ -1865,9 +1876,9 @@ CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConversionFunctionName && "Name must refer to a conversion function"); - return new (C) CXXConversionDecl(RD, StartLoc, NameInfo, T, TInfo, - isInline, isExplicit, isConstexpr, - EndLocation); + return new (C, RD) CXXConversionDecl(C, RD, StartLoc, NameInfo, T, TInfo, + isInline, isExplicit, isConstexpr, + EndLocation); } bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { @@ -1883,13 +1894,13 @@ LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, SourceLocation LangLoc, LanguageIDs Lang, bool HasBraces) { - return new (C) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, HasBraces); + return new (C, DC) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, HasBraces); } -LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(LinkageSpecDecl)); - return new (Mem) LinkageSpecDecl(0, SourceLocation(), SourceLocation(), - lang_c, false); +LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) LinkageSpecDecl(nullptr, SourceLocation(), + SourceLocation(), lang_c, false); } void UsingDirectiveDecl::anchor() { } @@ -1903,16 +1914,16 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, DeclContext *CommonAncestor) { if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used)) Used = NS->getOriginalNamespace(); - return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc, - IdentLoc, Used, CommonAncestor); + return new (C, DC) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc, + IdentLoc, Used, CommonAncestor); } -UsingDirectiveDecl * -UsingDirectiveDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingDirectiveDecl)); - return new (Mem) UsingDirectiveDecl(0, SourceLocation(), SourceLocation(), - NestedNameSpecifierLoc(), - SourceLocation(), 0, 0); +UsingDirectiveDecl *UsingDirectiveDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) UsingDirectiveDecl(nullptr, SourceLocation(), + SourceLocation(), + NestedNameSpecifierLoc(), + SourceLocation(), nullptr, nullptr); } NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { @@ -1922,17 +1933,14 @@ NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { return cast_or_null<NamespaceDecl>(NominatedNamespace); } -void NamespaceDecl::anchor() { } - -NamespaceDecl::NamespaceDecl(DeclContext *DC, bool Inline, - SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - NamespaceDecl *PrevDecl) - : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), - LocStart(StartLoc), RBraceLoc(), AnonOrFirstNamespaceAndInline(0, Inline) -{ +NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, NamespaceDecl *PrevDecl) + : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), + redeclarable_base(C), LocStart(StartLoc), RBraceLoc(), + AnonOrFirstNamespaceAndInline(nullptr, Inline) { setPreviousDecl(PrevDecl); - + if (PrevDecl) AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace()); } @@ -1941,13 +1949,23 @@ NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, NamespaceDecl *PrevDecl) { - return new (C) NamespaceDecl(DC, Inline, StartLoc, IdLoc, Id, PrevDecl); + return new (C, DC) NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id, + PrevDecl); } NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NamespaceDecl)); - return new (Mem) NamespaceDecl(0, false, SourceLocation(), SourceLocation(), - 0, 0); + return new (C, ID) NamespaceDecl(C, nullptr, false, SourceLocation(), + SourceLocation(), nullptr, nullptr); +} + +NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() { + return getNextRedeclaration(); +} +NamespaceDecl *NamespaceDecl::getPreviousDeclImpl() { + return getPreviousDecl(); +} +NamespaceDecl *NamespaceDecl::getMostRecentDeclImpl() { + return getMostRecentDecl(); } void NamespaceAliasDecl::anchor() { } @@ -1961,24 +1979,24 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, NamedDecl *Namespace) { if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace)) Namespace = NS->getOriginalNamespace(); - return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, - QualifierLoc, IdentLoc, Namespace); + return new (C, DC) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, + QualifierLoc, IdentLoc, Namespace); } NamespaceAliasDecl * NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NamespaceAliasDecl)); - return new (Mem) NamespaceAliasDecl(0, SourceLocation(), SourceLocation(), 0, - NestedNameSpecifierLoc(), - SourceLocation(), 0); + return new (C, ID) NamespaceAliasDecl(nullptr, SourceLocation(), + SourceLocation(), nullptr, + NestedNameSpecifierLoc(), + SourceLocation(), nullptr); } void UsingShadowDecl::anchor() { } UsingShadowDecl * UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingShadowDecl)); - return new (Mem) UsingShadowDecl(0, SourceLocation(), 0, 0); + return new (C, ID) UsingShadowDecl(C, nullptr, SourceLocation(), + nullptr, nullptr); } UsingDecl *UsingShadowDecl::getUsingDecl() const { @@ -2026,13 +2044,13 @@ UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool HasTypename) { - return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename); + return new (C, DC) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename); } UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingDecl)); - return new (Mem) UsingDecl(0, SourceLocation(), NestedNameSpecifierLoc(), - DeclarationNameInfo(), false); + return new (C, ID) UsingDecl(nullptr, SourceLocation(), + NestedNameSpecifierLoc(), DeclarationNameInfo(), + false); } SourceRange UsingDecl::getSourceRange() const { @@ -2048,16 +2066,16 @@ UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) { - return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc, - QualifierLoc, NameInfo); + return new (C, DC) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc, + QualifierLoc, NameInfo); } UnresolvedUsingValueDecl * UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UnresolvedUsingValueDecl)); - return new (Mem) UnresolvedUsingValueDecl(0, QualType(), SourceLocation(), - NestedNameSpecifierLoc(), - DeclarationNameInfo()); + return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(), + SourceLocation(), + NestedNameSpecifierLoc(), + DeclarationNameInfo()); } SourceRange UnresolvedUsingValueDecl::getSourceRange() const { @@ -2075,20 +2093,16 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, DeclarationName TargetName) { - return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc, - QualifierLoc, TargetNameLoc, - TargetName.getAsIdentifierInfo()); + return new (C, DC) UnresolvedUsingTypenameDecl( + DC, UsingLoc, TypenameLoc, QualifierLoc, TargetNameLoc, + TargetName.getAsIdentifierInfo()); } UnresolvedUsingTypenameDecl * UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, - sizeof(UnresolvedUsingTypenameDecl)); - return new (Mem) UnresolvedUsingTypenameDecl(0, SourceLocation(), - SourceLocation(), - NestedNameSpecifierLoc(), - SourceLocation(), - 0); + return new (C, ID) UnresolvedUsingTypenameDecl( + nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(), + SourceLocation(), nullptr); } void StaticAssertDecl::anchor() { } @@ -2099,15 +2113,30 @@ StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, StringLiteral *Message, SourceLocation RParenLoc, bool Failed) { - return new (C) StaticAssertDecl(DC, StaticAssertLoc, AssertExpr, Message, - RParenLoc, Failed); + return new (C, DC) StaticAssertDecl(DC, StaticAssertLoc, AssertExpr, Message, + RParenLoc, Failed); } -StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C, +StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(StaticAssertDecl)); - return new (Mem) StaticAssertDecl(0, SourceLocation(), 0, 0, - SourceLocation(), false); + return new (C, ID) StaticAssertDecl(nullptr, SourceLocation(), nullptr, + nullptr, SourceLocation(), false); +} + +MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName N, + QualType T, TypeSourceInfo *TInfo, + SourceLocation StartL, + IdentifierInfo *Getter, + IdentifierInfo *Setter) { + return new (C, DC) MSPropertyDecl(DC, L, N, T, TInfo, StartL, Getter, Setter); +} + +MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) MSPropertyDecl(nullptr, SourceLocation(), + DeclarationName(), QualType(), nullptr, + SourceLocation(), nullptr, nullptr); } static const char *getAccessName(AccessSpecifier AS) { diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp index 1c639d6..a996cab 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp @@ -46,25 +46,21 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, } #endif - std::size_t Size = sizeof(FriendDecl) - + FriendTypeTPLists.size() * sizeof(TemplateParameterList*); - void *Mem = C.Allocate(Size); - FriendDecl *FD = new (Mem) FriendDecl(DC, L, Friend, FriendL, - FriendTypeTPLists); + std::size_t Extra = FriendTypeTPLists.size() * sizeof(TemplateParameterList*); + FriendDecl *FD = new (C, DC, Extra) FriendDecl(DC, L, Friend, FriendL, + FriendTypeTPLists); cast<CXXRecordDecl>(DC)->pushFriendDecl(FD); return FD; } FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned FriendTypeNumTPLists) { - std::size_t Size = sizeof(FriendDecl) - + FriendTypeNumTPLists * sizeof(TemplateParameterList*); - void *Mem = AllocateDeserializedDecl(C, ID, Size); - return new (Mem) FriendDecl(EmptyShell(), FriendTypeNumTPLists); + std::size_t Extra = FriendTypeNumTPLists * sizeof(TemplateParameterList*); + return new (C, ID, Extra) FriendDecl(EmptyShell(), FriendTypeNumTPLists); } FriendDecl *CXXRecordDecl::getFirstFriend() const { ExternalASTSource *Source = getParentASTContext().getExternalSource(); Decl *First = data().FirstFriend.get(Source); - return First ? cast<FriendDecl>(First) : 0; + return First ? cast<FriendDecl>(First) : nullptr; } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index b2b5b70..2204dff 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -25,7 +25,7 @@ using namespace clang; //===----------------------------------------------------------------------===// void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) { - List = 0; + List = nullptr; if (Elts == 0) return; // Setting to an empty list is a noop. @@ -60,7 +60,7 @@ ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const { if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar)) return ivar; } - return 0; + return nullptr; } // Get the local instance/class method declared in this interface. @@ -72,7 +72,7 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance, if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) { if (const ObjCProtocolDecl *Def = Proto->getDefinition()) if (Def->isHidden() && !AllowHidden) - return 0; + return nullptr; } // Since instance & class methods can have the same name, the loop below @@ -90,7 +90,7 @@ ObjCContainerDecl::getMethod(Selector Sel, bool isInstance, if (MD && MD->isInstanceMethod() == isInstance) return MD; } - return 0; + return nullptr; } /// HasUserDeclaredSetterMethod - This routine returns 'true' if a user declared setter @@ -112,11 +112,7 @@ ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property) if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(this)) { // Also look into categories, including class extensions, looking // for a user declared instance method. - for (ObjCInterfaceDecl::visible_categories_iterator - Cat = ID->visible_categories_begin(), - CatEnd = ID->visible_categories_end(); - Cat != CatEnd; - ++Cat) { + for (const auto *Cat : ID->visible_categories()) { if (ObjCMethodDecl *MD = Cat->getInstanceMethod(Sel)) if (!MD->isImplicit()) return true; @@ -125,8 +121,7 @@ ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property) // Also search through the categories looking for a 'readwrite' declaration // of this property. If one found, presumably a setter will be provided // (properties declared in categories will not get auto-synthesized). - for (ObjCContainerDecl::prop_iterator P = Cat->prop_begin(), - E = Cat->prop_end(); P != E; ++P) + for (const auto *P : Cat->properties()) if (P->getIdentifier() == Property->getIdentifier()) { if (P->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) return true; @@ -135,13 +130,10 @@ ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property) } // Also look into protocols, for a user declared instance method. - for (ObjCInterfaceDecl::all_protocol_iterator P = - ID->all_referenced_protocol_begin(), - PE = ID->all_referenced_protocol_end(); P != PE; ++P) { - ObjCProtocolDecl *Proto = (*P); + for (const auto *Proto : ID->all_referenced_protocols()) if (Proto->HasUserDeclaredSetterMethod(Property)) return true; - } + // And in its super class. ObjCInterfaceDecl *OSC = ID->getSuperClass(); while (OSC) { @@ -151,11 +143,9 @@ ObjCContainerDecl::HasUserDeclaredSetterMethod(const ObjCPropertyDecl *Property) } } if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(this)) - for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(), - E = PD->protocol_end(); PI != E; ++PI) { - if ((*PI)->HasUserDeclaredSetterMethod(Property)) + for (const auto *PI : PD->protocols()) + if (PI->HasUserDeclaredSetterMethod(Property)) return true; - } return false; } @@ -167,7 +157,7 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) { if (const ObjCProtocolDecl *Def = Proto->getDefinition()) if (Def->isHidden()) - return 0; + return nullptr; } DeclContext::lookup_const_result R = DC->lookup(propertyID); @@ -176,7 +166,7 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I)) return PD; - return 0; + return nullptr; } IdentifierInfo * @@ -197,7 +187,7 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) { if (const ObjCProtocolDecl *Def = Proto->getDefinition()) if (Def->isHidden()) - return 0; + return nullptr; } if (ObjCPropertyDecl *PD = @@ -209,29 +199,23 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { break; case Decl::ObjCProtocol: { const ObjCProtocolDecl *PID = cast<ObjCProtocolDecl>(this); - for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(), - E = PID->protocol_end(); I != E; ++I) - if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) + for (const auto *I : PID->protocols()) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) return P; break; } case Decl::ObjCInterface: { const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this); // Look through categories (but not extensions). - for (ObjCInterfaceDecl::visible_categories_iterator - Cat = OID->visible_categories_begin(), - CatEnd = OID->visible_categories_end(); - Cat != CatEnd; ++Cat) { + for (const auto *Cat : OID->visible_categories()) { if (!Cat->IsClassExtension()) if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId)) return P; } // Look through protocols. - for (ObjCInterfaceDecl::all_protocol_iterator - I = OID->all_referenced_protocol_begin(), - E = OID->all_referenced_protocol_end(); I != E; ++I) - if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) + for (const auto *I : OID->all_referenced_protocols()) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) return P; // Finally, check the super class. @@ -243,15 +227,13 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { const ObjCCategoryDecl *OCD = cast<ObjCCategoryDecl>(this); // Look through protocols. if (!OCD->IsClassExtension()) - for (ObjCCategoryDecl::protocol_iterator - I = OCD->protocol_begin(), E = OCD->protocol_end(); I != E; ++I) - if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) - return P; - + for (const auto *I : OCD->protocols()) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + return P; break; } } - return 0; + return nullptr; } void ObjCInterfaceDecl::anchor() { } @@ -265,8 +247,8 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( IdentifierInfo *PropertyId) const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) - return 0; - + return nullptr; + if (data().ExternallyCompleted) LoadExternalDefinition(); @@ -275,27 +257,21 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( return PD; // Look through protocols. - for (ObjCInterfaceDecl::all_protocol_iterator - I = all_referenced_protocol_begin(), - E = all_referenced_protocol_end(); I != E; ++I) - if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) + for (const auto *I : all_referenced_protocols()) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) return P; - return 0; + return nullptr; } void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM, PropertyDeclOrder &PO) const { - for (ObjCContainerDecl::prop_iterator P = prop_begin(), - E = prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = *P; + for (auto *Prop : properties()) { PM[Prop->getIdentifier()] = Prop; PO.push_back(Prop); } - for (ObjCInterfaceDecl::all_protocol_iterator - PI = all_referenced_protocol_begin(), - E = all_referenced_protocol_end(); PI != E; ++PI) - (*PI)->collectPropertiesToImplement(PM, PO); + for (const auto *PI : all_referenced_protocols()) + PI->collectPropertiesToImplement(PM, PO); // Note, the properties declared only in class extensions are still copied // into the main @interface's property list, and therefore we don't // explicitly, have to search class extension properties. @@ -318,7 +294,7 @@ const ObjCInterfaceDecl *ObjCInterfaceDecl::isObjCRequiresPropertyDefs() const { return Class; Class = Class->getSuperClass(); } - return 0; + return nullptr; } void ObjCInterfaceDecl::mergeClassExtensionProtocolList( @@ -341,10 +317,7 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( for (unsigned i = 0; i < ExtNum; i++) { bool protocolExists = false; ObjCProtocolDecl *ProtoInExtension = ExtList[i]; - for (all_protocol_iterator - p = all_referenced_protocol_begin(), - e = all_referenced_protocol_end(); p != e; ++p) { - ObjCProtocolDecl *Proto = (*p); + for (auto *Proto : all_referenced_protocols()) { if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) { protocolExists = true; break; @@ -360,14 +333,132 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( return; // Merge ProtocolRefs into class's protocol list; - for (all_protocol_iterator p = all_referenced_protocol_begin(), - e = all_referenced_protocol_end(); p != e; ++p) { - ProtocolRefs.push_back(*p); + for (auto *P : all_referenced_protocols()) { + ProtocolRefs.push_back(P); } data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C); } +const ObjCInterfaceDecl * +ObjCInterfaceDecl::findInterfaceWithDesignatedInitializers() const { + const ObjCInterfaceDecl *IFace = this; + while (IFace) { + if (IFace->hasDesignatedInitializers()) + return IFace; + if (!IFace->inheritsDesignatedInitializers()) + break; + IFace = IFace->getSuperClass(); + } + return nullptr; +} + +static bool isIntroducingInitializers(const ObjCInterfaceDecl *D) { + for (const auto *MD : D->instance_methods()) { + if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) + return true; + } + for (const auto *Ext : D->visible_extensions()) { + for (const auto *MD : Ext->instance_methods()) { + if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) + return true; + } + } + if (const auto *ImplD = D->getImplementation()) { + for (const auto *MD : ImplD->instance_methods()) { + if (MD->getMethodFamily() == OMF_init && !MD->isOverriding()) + return true; + } + } + return false; +} + +bool ObjCInterfaceDecl::inheritsDesignatedInitializers() const { + switch (data().InheritedDesignatedInitializers) { + case DefinitionData::IDI_Inherited: + return true; + case DefinitionData::IDI_NotInherited: + return false; + case DefinitionData::IDI_Unknown: { + // If the class introduced initializers we conservatively assume that we + // don't know if any of them is a designated initializer to avoid possible + // misleading warnings. + if (isIntroducingInitializers(this)) { + data().InheritedDesignatedInitializers = DefinitionData::IDI_NotInherited; + } else { + if (auto SuperD = getSuperClass()) { + data().InheritedDesignatedInitializers = + SuperD->declaresOrInheritsDesignatedInitializers() ? + DefinitionData::IDI_Inherited : + DefinitionData::IDI_NotInherited; + } else { + data().InheritedDesignatedInitializers = + DefinitionData::IDI_NotInherited; + } + } + assert(data().InheritedDesignatedInitializers + != DefinitionData::IDI_Unknown); + return data().InheritedDesignatedInitializers == + DefinitionData::IDI_Inherited; + } + } + + llvm_unreachable("unexpected InheritedDesignatedInitializers value"); +} + +void ObjCInterfaceDecl::getDesignatedInitializers( + llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const { + // Check for a complete definition and recover if not so. + if (!isThisDeclarationADefinition()) + return; + if (data().ExternallyCompleted) + LoadExternalDefinition(); + + const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers(); + if (!IFace) + return; + + for (const auto *MD : IFace->instance_methods()) + if (MD->isThisDeclarationADesignatedInitializer()) + Methods.push_back(MD); + for (const auto *Ext : IFace->visible_extensions()) { + for (const auto *MD : Ext->instance_methods()) + if (MD->isThisDeclarationADesignatedInitializer()) + Methods.push_back(MD); + } +} + +bool ObjCInterfaceDecl::isDesignatedInitializer(Selector Sel, + const ObjCMethodDecl **InitMethod) const { + // Check for a complete definition and recover if not so. + if (!isThisDeclarationADefinition()) + return false; + if (data().ExternallyCompleted) + LoadExternalDefinition(); + + const ObjCInterfaceDecl *IFace= findInterfaceWithDesignatedInitializers(); + if (!IFace) + return false; + + if (const ObjCMethodDecl *MD = IFace->getInstanceMethod(Sel)) { + if (MD->isThisDeclarationADesignatedInitializer()) { + if (InitMethod) + *InitMethod = MD; + return true; + } + } + for (const auto *Ext : IFace->visible_extensions()) { + if (const ObjCMethodDecl *MD = Ext->getInstanceMethod(Sel)) { + if (MD->isThisDeclarationADesignatedInitializer()) { + if (InitMethod) + *InitMethod = MD; + return true; + } + } + } + return false; +} + void ObjCInterfaceDecl::allocateDefinitionData() { assert(!hasDefinition() && "ObjC class already has a definition"); Data.setPointer(new (getASTContext()) DefinitionData()); @@ -382,9 +473,8 @@ void ObjCInterfaceDecl::startDefinition() { allocateDefinitionData(); // Update all of the declarations with a pointer to the definition. - for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); - RD != RDEnd; ++RD) { - if (*RD != this) + for (auto RD : redecls()) { + if (RD != this) RD->Data = Data; } } @@ -393,22 +483,19 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, ObjCInterfaceDecl *&clsDeclared) { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) - return 0; + return nullptr; if (data().ExternallyCompleted) LoadExternalDefinition(); ObjCInterfaceDecl* ClassDecl = this; - while (ClassDecl != NULL) { + while (ClassDecl != nullptr) { if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) { clsDeclared = ClassDecl; return I; } - for (ObjCInterfaceDecl::visible_extensions_iterator - Ext = ClassDecl->visible_extensions_begin(), - ExtEnd = ClassDecl->visible_extensions_end(); - Ext != ExtEnd; ++Ext) { + for (const auto *Ext : ClassDecl->visible_extensions()) { if (ObjCIvarDecl *I = Ext->getIvarDecl(ID)) { clsDeclared = ClassDecl; return I; @@ -417,7 +504,7 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, ClassDecl = ClassDecl->getSuperClass(); } - return NULL; + return nullptr; } /// lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super @@ -427,29 +514,27 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( const IdentifierInfo*ICName) { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) - return 0; + return nullptr; if (data().ExternallyCompleted) LoadExternalDefinition(); ObjCInterfaceDecl* ClassDecl = this; - while (ClassDecl != NULL) { + while (ClassDecl != nullptr) { if (ClassDecl->getIdentifier() == ICName) return ClassDecl; ClassDecl = ClassDecl->getSuperClass(); } - return NULL; + return nullptr; } ObjCProtocolDecl * ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) { - for (ObjCInterfaceDecl::all_protocol_iterator P = - all_referenced_protocol_begin(), PE = all_referenced_protocol_end(); - P != PE; ++P) - if ((*P)->lookupProtocolNamed(Name)) - return (*P); + for (auto *P : all_referenced_protocols()) + if (P->lookupProtocolNamed(Name)) + return P; ObjCInterfaceDecl *SuperClass = getSuperClass(); - return SuperClass ? SuperClass->lookupNestedProtocol(Name) : NULL; + return SuperClass ? SuperClass->lookupNestedProtocol(Name) : nullptr; } /// lookupMethod - This method returns an instance/class method by looking in @@ -457,37 +542,34 @@ ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) { /// When argument category "C" is specified, any implicit method found /// in this category is ignored. ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, - bool isInstance, - bool shallowCategoryLookup, - const ObjCCategoryDecl *C) const { + bool isInstance, + bool shallowCategoryLookup, + bool followSuper, + const ObjCCategoryDecl *C) const +{ // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) - return 0; + return nullptr; const ObjCInterfaceDecl* ClassDecl = this; - ObjCMethodDecl *MethodDecl = 0; + ObjCMethodDecl *MethodDecl = nullptr; if (data().ExternallyCompleted) LoadExternalDefinition(); - while (ClassDecl != NULL) { + while (ClassDecl) { if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) return MethodDecl; // Didn't find one yet - look through protocols. - for (ObjCInterfaceDecl::protocol_iterator I = ClassDecl->protocol_begin(), - E = ClassDecl->protocol_end(); - I != E; ++I) - if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) + for (const auto *I : ClassDecl->protocols()) + if ((MethodDecl = I->lookupMethod(Sel, isInstance))) return MethodDecl; // Didn't find one yet - now look through categories. - for (ObjCInterfaceDecl::visible_categories_iterator - Cat = ClassDecl->visible_categories_begin(), - CatEnd = ClassDecl->visible_categories_end(); - Cat != CatEnd; ++Cat) { + for (const auto *Cat : ClassDecl->visible_categories()) { if ((MethodDecl = Cat->getMethod(Sel, isInstance))) - if (C != (*Cat) || !MethodDecl->isImplicit()) + if (C != Cat || !MethodDecl->isImplicit()) return MethodDecl; if (!shallowCategoryLookup) { @@ -497,14 +579,18 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) - if (C != (*Cat) || !MethodDecl->isImplicit()) + if (C != Cat || !MethodDecl->isImplicit()) return MethodDecl; } } - + + if (!followSuper) + return nullptr; + + // Get the super class (if any). ClassDecl = ClassDecl->getSuperClass(); } - return NULL; + return nullptr; } // Will search "local" class/category implementations for a method decl. @@ -515,12 +601,12 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( bool Instance) const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) - return 0; + return nullptr; if (data().ExternallyCompleted) LoadExternalDefinition(); - ObjCMethodDecl *Method = 0; + ObjCMethodDecl *Method = nullptr; if (ObjCImplementationDecl *ImpDecl = getImplementation()) Method = Instance ? ImpDecl->getInstanceMethod(Sel) : ImpDecl->getClassMethod(Sel); @@ -550,31 +636,38 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( // ObjCMethodDecl //===----------------------------------------------------------------------===// -ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C, - SourceLocation beginLoc, - SourceLocation endLoc, - Selector SelInfo, QualType T, - TypeSourceInfo *ResultTInfo, - DeclContext *contextDecl, - bool isInstance, - bool isVariadic, - bool isPropertyAccessor, - bool isImplicitlyDeclared, - bool isDefined, - ImplementationControl impControl, - bool HasRelatedResultType) { - return new (C) ObjCMethodDecl(beginLoc, endLoc, - SelInfo, T, ResultTInfo, contextDecl, - isInstance, isVariadic, isPropertyAccessor, - isImplicitlyDeclared, isDefined, - impControl, - HasRelatedResultType); +ObjCMethodDecl *ObjCMethodDecl::Create( + ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, + Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, + DeclContext *contextDecl, bool isInstance, bool isVariadic, + bool isPropertyAccessor, bool isImplicitlyDeclared, bool isDefined, + ImplementationControl impControl, bool HasRelatedResultType) { + return new (C, contextDecl) ObjCMethodDecl( + beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance, + isVariadic, isPropertyAccessor, isImplicitlyDeclared, isDefined, + impControl, HasRelatedResultType); } ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCMethodDecl)); - return new (Mem) ObjCMethodDecl(SourceLocation(), SourceLocation(), - Selector(), QualType(), 0, 0); + return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(), + Selector(), QualType(), nullptr, nullptr); +} + +bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const { + return getMethodFamily() == OMF_init && + hasAttr<ObjCDesignatedInitializerAttr>(); +} + +bool ObjCMethodDecl::isDesignatedInitializerForTheInterface( + const ObjCMethodDecl **InitMethod) const { + if (getMethodFamily() != OMF_init) + return false; + const DeclContext *DC = getDeclContext(); + if (isa<ObjCProtocolDecl>(DC)) + return false; + if (const ObjCInterfaceDecl *ID = getClassInterface()) + return ID->isDesignatedInitializer(getSelector(), InitMethod); + return false; } Stmt *ObjCMethodDecl::getBody() const { @@ -591,7 +684,7 @@ void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) { void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C, ArrayRef<ParmVarDecl*> Params, ArrayRef<SourceLocation> SelLocs) { - ParamsAndSelLocs = 0; + ParamsAndSelLocs = nullptr; NumParams = Params.size(); if (Params.empty() && SelLocs.empty()) return; @@ -628,9 +721,9 @@ void ObjCMethodDecl::setMethodParams(ASTContext &C, /// \brief A definition will return its interface declaration. /// An interface declaration will return its definition. /// Otherwise it will return itself. -ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() { +ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() { ASTContext &Ctx = getASTContext(); - ObjCMethodDecl *Redecl = 0; + ObjCMethodDecl *Redecl = nullptr; if (HasRedeclaration) Redecl = const_cast<ObjCMethodDecl*>(Ctx.getObjCMethodRedeclaration(this)); if (Redecl) @@ -730,7 +823,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { // init only has a conventional meaning for an instance method, and // it has to return an object. case OMF_init: - if (!isInstanceMethod() || !getResultType()->isObjCObjectPointerType()) + if (!isInstanceMethod() || !getReturnType()->isObjCObjectPointerType()) family = OMF_None; break; @@ -740,7 +833,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { case OMF_copy: case OMF_mutableCopy: case OMF_new: - if (!getResultType()->isObjCObjectPointerType()) + if (!getReturnType()->isObjCObjectPointerType()) family = OMF_None; break; @@ -757,15 +850,14 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { break; case OMF_performSelector: - if (!isInstanceMethod() || - !getResultType()->isObjCIdType()) + if (!isInstanceMethod() || !getReturnType()->isObjCIdType()) family = OMF_None; else { unsigned noParams = param_size(); if (noParams < 1 || noParams > 3) family = OMF_None; else { - ObjCMethodDecl::arg_type_iterator it = arg_type_begin(); + ObjCMethodDecl::param_type_iterator it = param_type_begin(); QualType ArgT = (*it); if (!ArgT->isObjCSelType()) { family = OMF_None; @@ -838,7 +930,7 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context, setSelfDecl(self); if (selfIsConsumed) - self->addAttr(new (Context) NSConsumedAttr(SourceLocation(), Context)); + self->addAttr(NSConsumedAttr::CreateImplicit(Context)); if (selfIsPseudoStrong) self->setARCPseudoStrong(true); @@ -855,8 +947,8 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { return CD->getClassInterface(); if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(getDeclContext())) return IMD->getClassInterface(); - - assert(!isa<ObjCProtocolDecl>(getDeclContext()) && "It's a protocol method"); + if (isa<ObjCProtocolDecl>(getDeclContext())) + return nullptr; llvm_unreachable("unknown method context"); } @@ -886,10 +978,8 @@ static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, return; } - for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), - PEnd = Category->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); + for (const auto *P : Category->protocols()) + CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); return; } @@ -906,26 +996,17 @@ static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, } if (const ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)){ - for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), - PEnd = Protocol->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); + for (const auto *P : Protocol->protocols()) + CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); } if (const ObjCInterfaceDecl * Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { - for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(), - PEnd = Interface->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethodsRecurse(*P, Method, Methods, MovedToSuper); - - for (ObjCInterfaceDecl::known_categories_iterator - Cat = Interface->known_categories_begin(), - CatEnd = Interface->known_categories_end(); - Cat != CatEnd; ++Cat) { - CollectOverriddenMethodsRecurse(*Cat, Method, Methods, - MovedToSuper); - } + for (const auto *P : Interface->protocols()) + CollectOverriddenMethodsRecurse(P, Method, Methods, MovedToSuper); + + for (const auto *Cat : Interface->known_categories()) + CollectOverriddenMethodsRecurse(Cat, Method, Methods, MovedToSuper); if (const ObjCInterfaceDecl *Super = Interface->getSuperClass()) return CollectOverriddenMethodsRecurse(Super, Method, Methods, @@ -1002,11 +1083,11 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { Selector Sel = getSelector(); unsigned NumArgs = Sel.getNumArgs(); if (NumArgs > 1) - return 0; + return nullptr; if (!isInstanceMethod() || getMethodFamily() != OMF_None) - return 0; - + return nullptr; + if (isPropertyAccessor()) { const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent()); // If container is class extension, find its primary class. @@ -1016,20 +1097,18 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { bool IsGetter = (NumArgs == 0); - for (ObjCContainerDecl::prop_iterator I = Container->prop_begin(), - E = Container->prop_end(); - I != E; ++I) { - Selector NextSel = IsGetter ? (*I)->getGetterName() - : (*I)->getSetterName(); + for (const auto *I : Container->properties()) { + Selector NextSel = IsGetter ? I->getGetterName() + : I->getSetterName(); if (NextSel == Sel) - return *I; + return I; } llvm_unreachable("Marked as a property accessor but no property found!"); } if (!CheckOverrides) - return 0; + return nullptr; typedef SmallVector<const ObjCMethodDecl *, 8> OverridesTy; OverridesTy Overrides; @@ -1040,8 +1119,7 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { return Prop; } - return 0; - + return nullptr; } //===----------------------------------------------------------------------===// @@ -1055,37 +1133,38 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C, ObjCInterfaceDecl *PrevDecl, SourceLocation ClassLoc, bool isInternal){ - ObjCInterfaceDecl *Result = new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, - PrevDecl, isInternal); + ObjCInterfaceDecl *Result = new (C, DC) + ObjCInterfaceDecl(C, DC, atLoc, Id, ClassLoc, PrevDecl, isInternal); Result->Data.setInt(!C.getLangOpts().Modules); C.getObjCInterfaceType(Result, PrevDecl); return Result; } -ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(ASTContext &C, +ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCInterfaceDecl)); - ObjCInterfaceDecl *Result = new (Mem) ObjCInterfaceDecl(0, SourceLocation(), - 0, SourceLocation(), - 0, false); + ObjCInterfaceDecl *Result = new (C, ID) ObjCInterfaceDecl(C, nullptr, + SourceLocation(), + nullptr, + SourceLocation(), + nullptr, false); Result->Data.setInt(!C.getLangOpts().Modules); return Result; } -ObjCInterfaceDecl:: -ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, - bool isInternal) - : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc), - TypeForDecl(0), Data() -{ +ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, + SourceLocation AtLoc, IdentifierInfo *Id, + SourceLocation CLoc, + ObjCInterfaceDecl *PrevDecl, + bool IsInternal) + : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc), + redeclarable_base(C), TypeForDecl(nullptr), Data() { setPreviousDecl(PrevDecl); // Copy the 'data' pointer over. if (PrevDecl) Data = PrevDecl->Data; - setImplicit(isInternal); + setImplicit(IsInternal); } void ObjCInterfaceDecl::LoadExternalDefinition() const { @@ -1103,6 +1182,40 @@ void ObjCInterfaceDecl::setExternallyCompleted() { data().ExternallyCompleted = true; } +void ObjCInterfaceDecl::setHasDesignatedInitializers() { + // Check for a complete definition and recover if not so. + if (!isThisDeclarationADefinition()) + return; + data().HasDesignatedInitializers = true; +} + +bool ObjCInterfaceDecl::hasDesignatedInitializers() const { + // Check for a complete definition and recover if not so. + if (!isThisDeclarationADefinition()) + return false; + if (data().ExternallyCompleted) + LoadExternalDefinition(); + + return data().HasDesignatedInitializers; +} + +StringRef +ObjCInterfaceDecl::getObjCRuntimeNameAsString() const { + if (ObjCRuntimeNameAttr *ObjCRTName = getAttr<ObjCRuntimeNameAttr>()) + return ObjCRTName->getMetadataName(); + + return getName(); +} + +StringRef +ObjCImplementationDecl::getObjCRuntimeNameAsString() const { + if (ObjCInterfaceDecl *ID = + const_cast<ObjCImplementationDecl*>(this)->getClassInterface()) + return ID->getObjCRuntimeNameAsString(); + + return getName(); +} + ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { if (const ObjCInterfaceDecl *Def = getDefinition()) { if (data().ExternallyCompleted) @@ -1113,7 +1226,7 @@ ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { } // FIXME: Should make sure no callers ever do this. - return 0; + return nullptr; } void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) { @@ -1146,9 +1259,9 @@ namespace { ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) - return 0; - - ObjCIvarDecl *curIvar = 0; + return nullptr; + + ObjCIvarDecl *curIvar = nullptr; if (!data().IvarList) { if (!ivar_empty()) { ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); @@ -1157,10 +1270,7 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { curIvar->setNextIvar(*I); } - for (ObjCInterfaceDecl::known_extensions_iterator - Ext = known_extensions_begin(), - ExtEnd = known_extensions_end(); - Ext != ExtEnd; ++Ext) { + for (const auto *Ext : known_extensions()) { if (!Ext->ivar_empty()) { ObjCCategoryDecl::ivar_iterator I = Ext->ivar_begin(), @@ -1184,19 +1294,17 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { data().IvarListMissingImplementation = false; if (!ImplDecl->ivar_empty()) { SmallVector<SynthesizeIvarChunk, 16> layout; - for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), - E = ImplDecl->ivar_end(); I != E; ++I) { - ObjCIvarDecl *IV = *I; + for (auto *IV : ImplDecl->ivars()) { if (IV->getSynthesize() && !IV->isInvalidDecl()) { layout.push_back(SynthesizeIvarChunk( IV->getASTContext().getTypeSize(IV->getType()), IV)); continue; } if (!data().IvarList) - data().IvarList = *I; + data().IvarList = IV; else - curIvar->setNextIvar(*I); - curIvar = *I; + curIvar->setNextIvar(IV); + curIvar = IV; } if (!layout.empty()) { @@ -1223,47 +1331,37 @@ ObjCCategoryDecl * ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) - return 0; + return nullptr; if (data().ExternallyCompleted) LoadExternalDefinition(); - for (visible_categories_iterator Cat = visible_categories_begin(), - CatEnd = visible_categories_end(); - Cat != CatEnd; - ++Cat) { + for (auto *Cat : visible_categories()) if (Cat->getIdentifier() == CategoryId) - return *Cat; - } - - return 0; + return Cat; + + return nullptr; } ObjCMethodDecl * ObjCInterfaceDecl::getCategoryInstanceMethod(Selector Sel) const { - for (visible_categories_iterator Cat = visible_categories_begin(), - CatEnd = visible_categories_end(); - Cat != CatEnd; - ++Cat) { + for (const auto *Cat : visible_categories()) { if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) if (ObjCMethodDecl *MD = Impl->getInstanceMethod(Sel)) return MD; } - return 0; + return nullptr; } ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const { - for (visible_categories_iterator Cat = visible_categories_begin(), - CatEnd = visible_categories_end(); - Cat != CatEnd; - ++Cat) { + for (const auto *Cat : visible_categories()) { if (ObjCCategoryImplDecl *Impl = Cat->getImplementation()) if (ObjCMethodDecl *MD = Impl->getClassMethod(Sel)) return MD; } - - return 0; + + return nullptr; } /// ClassImplementsProtocol - Checks that 'lProto' protocol @@ -1277,9 +1375,8 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, ObjCInterfaceDecl *IDecl = this; // 1st, look up the class. - for (ObjCInterfaceDecl::protocol_iterator - PI = IDecl->protocol_begin(), E = IDecl->protocol_end(); PI != E; ++PI){ - if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI)) + for (auto *PI : IDecl->protocols()){ + if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI)) return true; // This is dubious and is added to be compatible with gcc. In gcc, it is // also allowed assigning a protocol-qualified 'id' type to a LHS object @@ -1288,20 +1385,15 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, // FIXME: Treat this as an extension, and flag this as an error when GCC // extensions are not enabled. if (RHSIsQualifiedID && - getASTContext().ProtocolCompatibleWithProtocol(*PI, lProto)) + getASTContext().ProtocolCompatibleWithProtocol(PI, lProto)) return true; } // 2nd, look up the category. if (lookupCategory) - for (visible_categories_iterator Cat = visible_categories_begin(), - CatEnd = visible_categories_end(); - Cat != CatEnd; - ++Cat) { - for (ObjCCategoryDecl::protocol_iterator PI = Cat->protocol_begin(), - E = Cat->protocol_end(); - PI != E; ++PI) - if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI)) + for (const auto *Cat : visible_categories()) { + for (auto *PI : Cat->protocols()) + if (getASTContext().ProtocolCompatibleWithProtocol(lProto, PI)) return true; } @@ -1325,8 +1417,7 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, - bool synthesized, - bool backingIvarReferencedInAccessor) { + bool synthesized) { if (DC) { // Ivar's can only appear in interfaces, implementations (via synthesized // properties), and class extensions (via direct declaration, or synthesized @@ -1350,17 +1441,17 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, else ID = cast<ObjCCategoryDecl>(DC)->getClassInterface(); } - ID->setIvarList(0); + ID->setIvarList(nullptr); } - return new (C) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, - ac, BW, synthesized, backingIvarReferencedInAccessor); + return new (C, DC) ObjCIvarDecl(DC, StartLoc, IdLoc, Id, T, TInfo, ac, BW, + synthesized); } ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCIvarDecl)); - return new (Mem) ObjCIvarDecl(0, SourceLocation(), SourceLocation(), 0, - QualType(), 0, ObjCIvarDecl::None, 0, false, false); + return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(), + nullptr, QualType(), nullptr, + ObjCIvarDecl::None, nullptr, false); } const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { @@ -1397,14 +1488,14 @@ ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, Expr *BW) { - return new (C) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW); + return new (C, DC) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW); } -ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C, +ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCAtDefsFieldDecl)); - return new (Mem) ObjCAtDefsFieldDecl(0, SourceLocation(), SourceLocation(), - 0, QualType(), 0); + return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(), + SourceLocation(), nullptr, QualType(), + nullptr); } //===----------------------------------------------------------------------===// @@ -1413,12 +1504,12 @@ ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C, void ObjCProtocolDecl::anchor() { } -ObjCProtocolDecl::ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id, - SourceLocation nameLoc, +ObjCProtocolDecl::ObjCProtocolDecl(ASTContext &C, DeclContext *DC, + IdentifierInfo *Id, SourceLocation nameLoc, SourceLocation atStartLoc, ObjCProtocolDecl *PrevDecl) - : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), Data() -{ + : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), + redeclarable_base(C), Data() { setPreviousDecl(PrevDecl); if (PrevDecl) Data = PrevDecl->Data; @@ -1429,17 +1520,17 @@ ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation nameLoc, SourceLocation atStartLoc, ObjCProtocolDecl *PrevDecl) { - ObjCProtocolDecl *Result - = new (C) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc, PrevDecl); + ObjCProtocolDecl *Result = + new (C, DC) ObjCProtocolDecl(C, DC, Id, nameLoc, atStartLoc, PrevDecl); Result->Data.setInt(!C.getLangOpts().Modules); return Result; } -ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, +ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCProtocolDecl)); - ObjCProtocolDecl *Result = new (Mem) ObjCProtocolDecl(0, 0, SourceLocation(), - SourceLocation(), 0); + ObjCProtocolDecl *Result = + new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(), + SourceLocation(), nullptr); Result->Data.setInt(!C.getLangOpts().Modules); return Result; } @@ -1450,32 +1541,32 @@ ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) { if (Name == getIdentifier()) return PDecl; - for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I) - if ((PDecl = (*I)->lookupProtocolNamed(Name))) + for (auto *I : protocols()) + if ((PDecl = I->lookupProtocolNamed(Name))) return PDecl; - return NULL; + return nullptr; } // lookupMethod - Lookup a instance/class method in the protocol and protocols // it inherited. ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, bool isInstance) const { - ObjCMethodDecl *MethodDecl = NULL; + ObjCMethodDecl *MethodDecl = nullptr; // If there is no definition or the definition is hidden, we don't find // anything. const ObjCProtocolDecl *Def = getDefinition(); if (!Def || Def->isHidden()) - return NULL; + return nullptr; if ((MethodDecl = getMethod(Sel, isInstance))) return MethodDecl; - for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I) - if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) + for (const auto *I : protocols()) + if ((MethodDecl = I->lookupMethod(Sel, isInstance))) return MethodDecl; - return NULL; + return nullptr; } void ObjCProtocolDecl::allocateDefinitionData() { @@ -1488,8 +1579,7 @@ void ObjCProtocolDecl::startDefinition() { allocateDefinitionData(); // Update all of the declarations with a pointer to the definition. - for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); - RD != RDEnd; ++RD) + for (auto RD : redecls()) RD->Data = this->Data; } @@ -1497,17 +1587,14 @@ void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM, PropertyDeclOrder &PO) const { if (const ObjCProtocolDecl *PDecl = getDefinition()) { - for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), - E = PDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = *P; + for (auto *Prop : PDecl->properties()) { // Insert into PM if not there already. PM.insert(std::make_pair(Prop->getIdentifier(), Prop)); PO.push_back(Prop); } // Scan through protocol's protocols. - for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), - E = PDecl->protocol_end(); PI != E; ++PI) - (*PI)->collectPropertiesToImplement(PM, PO); + for (const auto *PI : PDecl->protocols()) + PI->collectPropertiesToImplement(PM, PO); } } @@ -1517,9 +1604,7 @@ void ObjCProtocolDecl::collectInheritedProtocolProperties( ProtocolPropertyMap &PM) const { if (const ObjCProtocolDecl *PDecl = getDefinition()) { bool MatchFound = false; - for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), - E = PDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = *P; + for (auto *Prop : PDecl->properties()) { if (Prop == Property) continue; if (Prop->getIdentifier() == Property->getIdentifier()) { @@ -1530,12 +1615,19 @@ void ObjCProtocolDecl::collectInheritedProtocolProperties( } // Scan through protocol's protocols which did not have a matching property. if (!MatchFound) - for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), - E = PDecl->protocol_end(); PI != E; ++PI) - (*PI)->collectInheritedProtocolProperties(Property, PM); + for (const auto *PI : PDecl->protocols()) + PI->collectInheritedProtocolProperties(Property, PM); } } +StringRef +ObjCProtocolDecl::getObjCRuntimeNameAsString() const { + if (ObjCRuntimeNameAttr *ObjCRTName = getAttr<ObjCRuntimeNameAttr>()) + return ObjCRTName->getMetadataName(); + + return getName(); +} + //===----------------------------------------------------------------------===// // ObjCCategoryDecl //===----------------------------------------------------------------------===// @@ -1543,17 +1635,16 @@ void ObjCProtocolDecl::collectInheritedProtocolProperties( void ObjCCategoryDecl::anchor() { } ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation AtLoc, + SourceLocation AtLoc, SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, IdentifierInfo *Id, ObjCInterfaceDecl *IDecl, SourceLocation IvarLBraceLoc, SourceLocation IvarRBraceLoc) { - ObjCCategoryDecl *CatDecl = new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, - CategoryNameLoc, Id, - IDecl, - IvarLBraceLoc, IvarRBraceLoc); + ObjCCategoryDecl *CatDecl = + new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id, + IDecl, IvarLBraceLoc, IvarRBraceLoc); if (IDecl) { // Link this category into its class's category list. CatDecl->NextClassCategory = IDecl->getCategoryListRaw(); @@ -1567,11 +1658,11 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC, return CatDecl; } -ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C, +ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCCategoryDecl)); - return new (Mem) ObjCCategoryDecl(0, SourceLocation(), SourceLocation(), - SourceLocation(), 0, 0); + return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(), + SourceLocation(), SourceLocation(), + nullptr, nullptr); } ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const { @@ -1599,22 +1690,22 @@ ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation CategoryNameLoc) { if (ClassInterface && ClassInterface->hasDefinition()) ClassInterface = ClassInterface->getDefinition(); - return new (C) ObjCCategoryImplDecl(DC, Id, ClassInterface, - nameLoc, atStartLoc, CategoryNameLoc); + return new (C, DC) ObjCCategoryImplDecl(DC, Id, ClassInterface, nameLoc, + atStartLoc, CategoryNameLoc); } ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCCategoryImplDecl)); - return new (Mem) ObjCCategoryImplDecl(0, 0, 0, SourceLocation(), - SourceLocation(), SourceLocation()); + return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr, + SourceLocation(), SourceLocation(), + SourceLocation()); } ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const { // The class interface might be NULL if we are working with invalid code. if (const ObjCInterfaceDecl *ID = getClassInterface()) return ID->FindCategoryDeclaration(getIdentifier()); - return 0; + return nullptr; } @@ -1649,13 +1740,11 @@ void ObjCImplDecl::setClassInterface(ObjCInterfaceDecl *IFace) { /// ObjCPropertyImplDecl *ObjCImplDecl:: FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { - for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){ - ObjCPropertyImplDecl *PID = *i; + for (auto *PID : property_impls()) if (PID->getPropertyIvarDecl() && PID->getPropertyIvarDecl()->getIdentifier() == ivarId) return PID; - } - return 0; + return nullptr; } /// FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl @@ -1664,12 +1753,10 @@ FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { /// ObjCPropertyImplDecl *ObjCImplDecl:: FindPropertyImplDecl(IdentifierInfo *Id) const { - for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){ - ObjCPropertyImplDecl *PID = *i; + for (auto *PID : property_impls()) if (PID->getPropertyDecl()->getIdentifier() == Id) return PID; - } - return 0; + return nullptr; } raw_ostream &clang::operator<<(raw_ostream &OS, @@ -1695,16 +1782,15 @@ ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IvarRBraceLoc) { if (ClassInterface && ClassInterface->hasDefinition()) ClassInterface = ClassInterface->getDefinition(); - return new (C) ObjCImplementationDecl(DC, ClassInterface, SuperDecl, - nameLoc, atStartLoc, superLoc, - IvarLBraceLoc, IvarRBraceLoc); + return new (C, DC) ObjCImplementationDecl(DC, ClassInterface, SuperDecl, + nameLoc, atStartLoc, superLoc, + IvarLBraceLoc, IvarRBraceLoc); } ObjCImplementationDecl * ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCImplementationDecl)); - return new (Mem) ObjCImplementationDecl(0, 0, 0, SourceLocation(), - SourceLocation()); + return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr, + SourceLocation(), SourceLocation()); } void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, @@ -1737,13 +1823,13 @@ ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, ObjCInterfaceDecl* AliasedClass) { - return new (C) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass); + return new (C, DC) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass); } ObjCCompatibleAliasDecl * ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCCompatibleAliasDecl)); - return new (Mem) ObjCCompatibleAliasDecl(0, SourceLocation(), 0, 0); + return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(), + nullptr, nullptr); } //===----------------------------------------------------------------------===// @@ -1759,15 +1845,14 @@ ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation LParenLoc, TypeSourceInfo *T, PropertyControl propControl) { - return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T); + return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T); } -ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C, +ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void * Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCPropertyDecl)); - return new (Mem) ObjCPropertyDecl(0, SourceLocation(), 0, SourceLocation(), - SourceLocation(), - 0); + return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr, + SourceLocation(), SourceLocation(), + nullptr); } //===----------------------------------------------------------------------===// @@ -1782,15 +1867,15 @@ ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C, Kind PK, ObjCIvarDecl *ivar, SourceLocation ivarLoc) { - return new (C) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar, - ivarLoc); + return new (C, DC) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar, + ivarLoc); } -ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C, +ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCPropertyImplDecl)); - return new (Mem) ObjCPropertyImplDecl(0, SourceLocation(), SourceLocation(), - 0, Dynamic, 0, SourceLocation()); + return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(), + SourceLocation(), nullptr, Dynamic, + nullptr, SourceLocation()); } SourceRange ObjCPropertyImplDecl::getSourceRange() const { diff --git a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp index 0d195f7..5f8b42b 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclBase.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclOpenMP.h" #include "clang/AST/Expr.h" @@ -29,12 +29,8 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef<Expr *> VL) { - unsigned Size = sizeof(OMPThreadPrivateDecl) + - (VL.size() * sizeof(Expr *)); - - void *Mem = C.Allocate(Size, llvm::alignOf<OMPThreadPrivateDecl>()); - OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate, - DC, L); + OMPThreadPrivateDecl *D = new (C, DC, VL.size() * sizeof(Expr *)) + OMPThreadPrivateDecl(OMPThreadPrivate, DC, L); D->NumVars = VL.size(); D->setVars(VL); return D; @@ -43,11 +39,8 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C, OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned N) { - unsigned Size = sizeof(OMPThreadPrivateDecl) + (N * sizeof(Expr *)); - - void *Mem = AllocateDeserializedDecl(C, ID, Size); - OMPThreadPrivateDecl *D = new (Mem) OMPThreadPrivateDecl(OMPThreadPrivate, - 0, SourceLocation()); + OMPThreadPrivateDecl *D = new (C, ID, N * sizeof(Expr *)) + OMPThreadPrivateDecl(OMPThreadPrivate, nullptr, SourceLocation()); D->NumVars = N; return D; } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index 767f662..e5e5130 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -85,7 +85,7 @@ namespace { void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); void PrintTemplateParameters(const TemplateParameterList *Params, - const TemplateArgumentList *Args = 0); + const TemplateArgumentList *Args = nullptr); void prettyPrintAttributes(Decl *D); }; } @@ -114,7 +114,7 @@ static QualType GetBaseType(QualType T) { else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType)) BaseType = ATy->getElementType(); else if (const FunctionType* FTy = BaseType->getAs<FunctionType>()) - BaseType = FTy->getResultType(); + BaseType = FTy->getReturnType(); else if (const VectorType *VTy = BaseType->getAs<VectorType>()) BaseType = VTy->getElementType(); else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>()) @@ -167,7 +167,7 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls, } } -void DeclContext::dumpDeclContext() const { +LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const { // Get the translation unit const DeclContext *DC = this; while (!DC->isTranslationUnit()) @@ -238,17 +238,6 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (D->isImplicit()) continue; - // FIXME: Ugly hack so we don't pretty-print the builtin declaration - // of __builtin_va_list or __[u]int128_t. There should be some other way - // to check that. - if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) { - if (IdentifierInfo *II = ND->getIdentifier()) { - if (II->isStr("__builtin_va_list") || - II->isStr("__int128_t") || II->isStr("__uint128_t")) - continue; - } - } - // The next bits of code handles stuff like "struct {int x;} a,b"; we're // forced to merge the declarations because there's no other way to // refer to the struct in question. This limited merging is safe without @@ -293,21 +282,21 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { Visit(*D); // FIXME: Need to be able to tell the DeclPrinter when - const char *Terminator = 0; + const char *Terminator = nullptr; if (isa<OMPThreadPrivateDecl>(*D)) - Terminator = 0; + Terminator = nullptr; else if (isa<FunctionDecl>(*D) && cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) - Terminator = 0; + Terminator = nullptr; else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) - Terminator = 0; + Terminator = nullptr; else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || isa<ObjCImplementationDecl>(*D) || isa<ObjCInterfaceDecl>(*D) || isa<ObjCProtocolDecl>(*D) || isa<ObjCCategoryImplDecl>(*D) || isa<ObjCCategoryDecl>(*D)) - Terminator = 0; + Terminator = nullptr; else if (isa<EnumConstantDecl>(*D)) { DeclContext::decl_iterator Next = D; ++Next; @@ -390,12 +379,13 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { Out << *D; if (Expr *Init = D->getInitExpr()) { Out << " = "; - Init->printPretty(Out, 0, Policy, Indentation); + Init->printPretty(Out, nullptr, Policy, Indentation); } } void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); + CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D); if (!Policy.SuppressSpecifiers) { switch (D->getStorageClass()) { case SC_None: break; @@ -409,7 +399,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->isInlineSpecified()) Out << "inline "; if (D->isVirtualAsWritten()) Out << "virtual "; if (D->isModulePrivate()) Out << "__module_private__ "; - if (CDecl && CDecl->isExplicitSpecified()) + if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr "; + if ((CDecl && CDecl->isExplicitSpecified()) || + (ConversionDecl && ConversionDecl->isExplicit())) Out << "explicit "; } @@ -423,9 +415,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Ty = PT->getInnerType(); } - if (isa<FunctionType>(Ty)) { - const FunctionType *AFT = Ty->getAs<FunctionType>(); - const FunctionProtoType *FT = 0; + if (const FunctionType *AFT = Ty->getAs<FunctionType>()) { + const FunctionProtoType *FT = nullptr; if (D->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(AFT); @@ -459,6 +450,17 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Proto += " volatile"; if (FT->isRestrict()) Proto += " restrict"; + + switch (FT->getRefQualifier()) { + case RQ_None: + break; + case RQ_LValue: + Proto += " &"; + break; + case RQ_RValue: + Proto += " &&"; + break; + } } if (FT && FT->hasDynamicExceptionSpec()) { @@ -478,7 +480,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (FT->getExceptionSpecType() == EST_ComputedNoexcept) { Proto += "("; llvm::raw_string_ostream EOut(Proto); - FT->getNoexceptExpr()->printPretty(EOut, 0, SubPolicy, + FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy, Indentation); EOut.flush(); Proto += EOut.str(); @@ -488,10 +490,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (CDecl) { bool HasInitializerList = false; - for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), - E = CDecl->init_end(); - B != E; ++B) { - CXXCtorInitializer *BMInitializer = (*B); + for (const auto *BMInitializer : CDecl->inits()) { if (BMInitializer->isInClassMemberInitializer()) continue; @@ -519,9 +518,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Init = Tmp->getSubExpr(); Init = Init->IgnoreParens(); - - Expr *SimpleInit = 0; - Expr **Args = 0; + + Expr *SimpleInit = nullptr; + Expr **Args = nullptr; unsigned NumArgs = 0; if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { Args = ParenList->getExprs(); @@ -534,29 +533,32 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { SimpleInit = Init; if (SimpleInit) - SimpleInit->printPretty(Out, 0, Policy, Indentation); + SimpleInit->printPretty(Out, nullptr, Policy, Indentation); else { for (unsigned I = 0; I != NumArgs; ++I) { + assert(Args[I] != nullptr && "Expected non-null Expr"); if (isa<CXXDefaultArgExpr>(Args[I])) break; if (I) Out << ", "; - Args[I]->printPretty(Out, 0, Policy, Indentation); + Args[I]->printPretty(Out, nullptr, Policy, Indentation); } } } Out << ")"; + if (BMInitializer->isPackExpansion()) + Out << "..."; } - if (!Proto.empty()) - Out << Proto; - } else { + } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) { if (FT && FT->hasTrailingReturn()) { Out << "auto " << Proto << " -> "; Proto.clear(); } - AFT->getResultType().print(Out, Policy, Proto); + AFT->getReturnType().print(Out, Policy, Proto); + Proto.clear(); } + Out << Proto; } else { Ty.print(Out, Policy, Proto); } @@ -585,7 +587,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } else Out << ' '; - D->getBody()->printPretty(Out, 0, SubPolicy, Indentation); + if (D->getBody()) + D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation); Out << '\n'; } } @@ -626,7 +629,7 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) { if (D->isBitField()) { Out << " : "; - D->getBitWidth()->printPretty(Out, 0, Policy, Indentation); + D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation); } Expr *Init = D->getInClassInitializer(); @@ -635,7 +638,7 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) { Out << " "; else Out << " = "; - Init->printPretty(Out, 0, Policy, Indentation); + Init->printPretty(Out, nullptr, Policy, Indentation); } prettyPrintAttributes(D); } @@ -690,7 +693,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { else if (D->getInitStyle() == VarDecl::CInit) { Out << " = "; } - Init->printPretty(Out, 0, Policy, Indentation); + Init->printPretty(Out, nullptr, Policy, Indentation); if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) Out << ")"; } @@ -704,7 +707,7 @@ void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { Out << "__asm ("; - D->getAsmString()->printPretty(Out, 0, Policy, Indentation); + D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation); Out << ")"; } @@ -715,9 +718,9 @@ void DeclPrinter::VisitImportDecl(ImportDecl *D) { void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { Out << "static_assert("; - D->getAssertExpr()->printPretty(Out, 0, Policy, Indentation); + D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation); Out << ", "; - D->getMessage()->printPretty(Out, 0, Policy, Indentation); + D->getMessage()->printPretty(Out, nullptr, Policy, Indentation); Out << ")"; } @@ -855,7 +858,8 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, Args->get(i).print(Policy, Out); } else if (NTTP->hasDefaultArgument()) { Out << " = "; - NTTP->getDefaultArgument()->printPretty(Out, 0, Policy, Indentation); + NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, + Indentation); } } else if (const TemplateTemplateParmDecl *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) { @@ -884,10 +888,9 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (PrintInstantiation) { TemplateParameterList *Params = D->getTemplateParameters(); - for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(), E = D->spec_end(); - I != E; ++I) { - PrintTemplateParameters(Params, (*I)->getTemplateSpecializationArgs()); - Visit(*I); + for (auto *I : D->specializations()) { + PrintTemplateParameters(Params, I->getTemplateSpecializationArgs()); + Visit(I); } } @@ -897,10 +900,9 @@ void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (PrintInstantiation) { TemplateParameterList *Params = D->getTemplateParameters(); - for (ClassTemplateDecl::spec_iterator I = D->spec_begin(), E = D->spec_end(); - I != E; ++I) { - PrintTemplateParameters(Params, &(*I)->getTemplateArgs()); - Visit(*I); + for (auto *I : D->specializations()) { + PrintTemplateParameters(Params, &I->getTemplateArgs()); + Visit(I); Out << '\n'; } } @@ -917,19 +919,19 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { Out << "- "; else Out << "+ "; - if (!OMD->getResultType().isNull()) - Out << '(' << OMD->getASTContext().getUnqualifiedObjCPointerType(OMD->getResultType()). - getAsString(Policy) << ")"; + if (!OMD->getReturnType().isNull()) + Out << '(' << OMD->getASTContext() + .getUnqualifiedObjCPointerType(OMD->getReturnType()) + .getAsString(Policy) << ")"; std::string name = OMD->getSelector().getAsString(); std::string::size_type pos, lastPos = 0; - for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), - E = OMD->param_end(); PI != E; ++PI) { + for (const auto *PI : OMD->params()) { // FIXME: selector is missing here! pos = name.find_first_of(':', lastPos); Out << " " << name.substr(lastPos, pos - lastPos); - Out << ":(" << (*PI)->getASTContext().getUnqualifiedObjCPointerType((*PI)->getType()). - getAsString(Policy) << ')' << **PI; + Out << ":(" << PI->getASTContext().getUnqualifiedObjCPointerType(PI->getType()). + getAsString(Policy) << ')' << *PI; lastPos = pos + 1; } @@ -941,7 +943,7 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { if (OMD->getBody() && !Policy.TerseOutput) { Out << ' '; - OMD->getBody()->printPretty(Out, 0, Policy); + OMD->getBody()->printPretty(Out, nullptr, Policy); Out << '\n'; } else if (Policy.PolishForDeclaration) @@ -960,10 +962,9 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { if (OID->ivar_size() > 0) { Out << "{\n"; Indentation += Policy.Indentation; - for (ObjCImplementationDecl::ivar_iterator I = OID->ivar_begin(), - E = OID->ivar_end(); I != E; ++I) { + for (const auto *I : OID->ivars()) { Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). - getAsString(Policy) << ' ' << **I << ";\n"; + getAsString(Policy) << ' ' << *I << ";\n"; } Indentation -= Policy.Indentation; Out << "}\n"; @@ -999,10 +1000,10 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { Out << "{\n"; eolnOut = true; Indentation += Policy.Indentation; - for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), - E = OID->ivar_end(); I != E; ++I) { - Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). - getAsString(Policy) << ' ' << **I << ";\n"; + for (const auto *I : OID->ivars()) { + Indent() << I->getASTContext() + .getUnqualifiedObjCPointerType(I->getType()) + .getAsString(Policy) << ' ' << *I << ";\n"; } Indentation -= Policy.Indentation; Out << "}\n"; @@ -1051,11 +1052,9 @@ void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { if (PID->ivar_size() > 0) { Out << "{\n"; Indentation += Policy.Indentation; - for (ObjCCategoryDecl::ivar_iterator I = PID->ivar_begin(), - E = PID->ivar_end(); I != E; ++I) { + for (const auto *I : PID->ivars()) Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()). - getAsString(Policy) << ' ' << **I << ";\n"; - } + getAsString(Policy) << ' ' << *I << ";\n"; Indentation -= Policy.Indentation; Out << "}\n"; } @@ -1090,13 +1089,13 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { } if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { - Out << (first ? ' ' : ',') << "getter = " - << PDecl->getGetterName().getAsString(); + Out << (first ? ' ' : ',') << "getter = "; + PDecl->getGetterName().print(Out); first = false; } if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { - Out << (first ? ' ' : ',') << "setter = " - << PDecl->getSetterName().getAsString(); + Out << (first ? ' ' : ',') << "setter = "; + PDecl->getSetterName().print(Out); first = false; } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index 7172fb7..0d1d2a4 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -164,13 +164,13 @@ template <class EntryType> typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType* RedeclarableTemplateDecl::findSpecializationImpl( llvm::FoldingSetVector<EntryType> &Specs, - const TemplateArgument *Args, unsigned NumArgs, + ArrayRef<TemplateArgument> Args, void *&InsertPos) { typedef SpecEntryTraits<EntryType> SETraits; llvm::FoldingSetNodeID ID; - EntryType::Profile(ID,Args,NumArgs, getASTContext()); + EntryType::Profile(ID,Args, getASTContext()); EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos); - return Entry ? SETraits::getMostRecentDecl(Entry) : 0; + return Entry ? SETraits::getMostRecentDecl(Entry) : nullptr; } /// \brief Generate the injected template arguments for the given template @@ -229,14 +229,13 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, TemplateParameterList *Params, NamedDecl *Decl) { AdoptTemplateParameterList(Params, cast<DeclContext>(Decl)); - return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); + return new (C, DC) FunctionTemplateDecl(C, DC, L, Name, Params, Decl); } FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionTemplateDecl)); - return new (Mem) FunctionTemplateDecl(0, SourceLocation(), DeclarationName(), - 0, 0); + return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(), + DeclarationName(), nullptr, nullptr); } RedeclarableTemplateDecl::CommonBase * @@ -251,7 +250,7 @@ void FunctionTemplateDecl::LoadLazySpecializations() const { if (CommonPtr->LazySpecializations) { ASTContext &Context = getASTContext(); uint32_t *Specs = CommonPtr->LazySpecializations; - CommonPtr->LazySpecializations = 0; + CommonPtr->LazySpecializations = nullptr; for (uint32_t I = 0, N = *Specs++; I != N; ++I) (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); } @@ -264,9 +263,9 @@ FunctionTemplateDecl::getSpecializations() const { } FunctionDecl * -FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args, - unsigned NumArgs, void *&InsertPos) { - return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos); +FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, + void *&InsertPos) { + return findSpecializationImpl(getSpecializations(), Args, InsertPos); } void FunctionTemplateDecl::addSpecialization( @@ -308,15 +307,16 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, NamedDecl *Decl, ClassTemplateDecl *PrevDecl) { AdoptTemplateParameterList(Params, cast<DeclContext>(Decl)); - ClassTemplateDecl *New = new (C) ClassTemplateDecl(DC, L, Name, Params, Decl); + ClassTemplateDecl *New = new (C, DC) ClassTemplateDecl(C, DC, L, Name, + Params, Decl); New->setPreviousDecl(PrevDecl); return New; } -ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C, +ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ClassTemplateDecl)); - return new (Mem) ClassTemplateDecl(EmptyShell()); + return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(), + DeclarationName(), nullptr, nullptr); } void ClassTemplateDecl::LoadLazySpecializations() const { @@ -324,7 +324,7 @@ void ClassTemplateDecl::LoadLazySpecializations() const { if (CommonPtr->LazySpecializations) { ASTContext &Context = getASTContext(); uint32_t *Specs = CommonPtr->LazySpecializations; - CommonPtr->LazySpecializations = 0; + CommonPtr->LazySpecializations = nullptr; for (uint32_t I = 0, N = *Specs++; I != N; ++I) (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); } @@ -350,9 +350,9 @@ ClassTemplateDecl::newCommon(ASTContext &C) const { } ClassTemplateSpecializationDecl * -ClassTemplateDecl::findSpecialization(const TemplateArgument *Args, - unsigned NumArgs, void *&InsertPos) { - return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos); +ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, + void *&InsertPos) { + return findSpecializationImpl(getSpecializations(), Args, InsertPos); } void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, @@ -370,11 +370,9 @@ void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, } ClassTemplatePartialSpecializationDecl * -ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args, - unsigned NumArgs, +ClassTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos) { - return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs, - InsertPos); + return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos); } void ClassTemplateDecl::AddPartialSpecialization( @@ -418,7 +416,7 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) { return P->getMostRecentDecl(); } - return 0; + return nullptr; } ClassTemplatePartialSpecializationDecl * @@ -433,7 +431,7 @@ ClassTemplateDecl::findPartialSpecInstantiatedFromMember( return P->getMostRecentDecl(); } - return 0; + return nullptr; } QualType @@ -471,17 +469,16 @@ TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack) { TemplateTypeParmDecl *TTPDecl = - new (C) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename); + new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename); QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl); - TTPDecl->TypeForDecl = TTPType.getTypePtr(); + TTPDecl->setTypeForDecl(TTPType.getTypePtr()); return TTPDecl; } TemplateTypeParmDecl * TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTypeParmDecl)); - return new (Mem) TemplateTypeParmDecl(0, SourceLocation(), SourceLocation(), - 0, false); + return new (C, ID) TemplateTypeParmDecl(nullptr, SourceLocation(), + SourceLocation(), nullptr, false); } SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { @@ -499,15 +496,15 @@ SourceRange TemplateTypeParmDecl::getSourceRange() const { } unsigned TemplateTypeParmDecl::getDepth() const { - return TypeForDecl->getAs<TemplateTypeParmType>()->getDepth(); + return getTypeForDecl()->getAs<TemplateTypeParmType>()->getDepth(); } unsigned TemplateTypeParmDecl::getIndex() const { - return TypeForDecl->getAs<TemplateTypeParmType>()->getIndex(); + return getTypeForDecl()->getAs<TemplateTypeParmType>()->getIndex(); } bool TemplateTypeParmDecl::isParameterPack() const { - return TypeForDecl->getAs<TemplateTypeParmType>()->isParameterPack(); + return getTypeForDecl()->getAs<TemplateTypeParmType>()->isParameterPack(); } //===----------------------------------------------------------------------===// @@ -525,7 +522,7 @@ NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC, unsigned NumExpandedTypes, TypeSourceInfo **ExpandedTInfos) : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), - TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false), + TemplateParmPosition(D, P), DefaultArgumentAndInherited(nullptr, false), ParameterPack(true), ExpandedParameterPack(true), NumExpandedTypes(NumExpandedTypes) { @@ -544,8 +541,8 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo) { - return new (C) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, - T, ParameterPack, TInfo); + return new (C, DC) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, + T, ParameterPack, TInfo); } NonTypeTemplateParmDecl * @@ -557,34 +554,26 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, const QualType *ExpandedTypes, unsigned NumExpandedTypes, TypeSourceInfo **ExpandedTInfos) { - unsigned Size = sizeof(NonTypeTemplateParmDecl) - + NumExpandedTypes * 2 * sizeof(void*); - void *Mem = C.Allocate(Size); - return new (Mem) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, - D, P, Id, T, TInfo, - ExpandedTypes, NumExpandedTypes, - ExpandedTInfos); + unsigned Extra = NumExpandedTypes * 2 * sizeof(void*); + return new (C, DC, Extra) NonTypeTemplateParmDecl( + DC, StartLoc, IdLoc, D, P, Id, T, TInfo, + ExpandedTypes, NumExpandedTypes, ExpandedTInfos); } NonTypeTemplateParmDecl * NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NonTypeTemplateParmDecl)); - return new (Mem) NonTypeTemplateParmDecl(0, SourceLocation(), - SourceLocation(), 0, 0, 0, - QualType(), false, 0); + return new (C, ID) NonTypeTemplateParmDecl(nullptr, SourceLocation(), + SourceLocation(), 0, 0, nullptr, + QualType(), false, nullptr); } NonTypeTemplateParmDecl * NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumExpandedTypes) { - unsigned Size = sizeof(NonTypeTemplateParmDecl) - + NumExpandedTypes * 2 * sizeof(void*); - - void *Mem = AllocateDeserializedDecl(C, ID, Size); - return new (Mem) NonTypeTemplateParmDecl(0, SourceLocation(), - SourceLocation(), 0, 0, 0, - QualType(), 0, 0, NumExpandedTypes, - 0); + unsigned Extra = NumExpandedTypes * 2 * sizeof(void*); + return new (C, ID, Extra) NonTypeTemplateParmDecl( + nullptr, SourceLocation(), SourceLocation(), 0, 0, nullptr, QualType(), + nullptr, nullptr, NumExpandedTypes, nullptr); } SourceRange NonTypeTemplateParmDecl::getSourceRange() const { @@ -624,8 +613,8 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateParameterList *Params) { - return new (C) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id, - Params); + return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id, + Params); } TemplateTemplateParmDecl * @@ -634,28 +623,23 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, IdentifierInfo *Id, TemplateParameterList *Params, ArrayRef<TemplateParameterList *> Expansions) { - void *Mem = C.Allocate(sizeof(TemplateTemplateParmDecl) + - sizeof(TemplateParameterList*) * Expansions.size()); - return new (Mem) TemplateTemplateParmDecl(DC, L, D, P, Id, Params, - Expansions.size(), - Expansions.data()); + return new (C, DC, sizeof(TemplateParameterList*) * Expansions.size()) + TemplateTemplateParmDecl(DC, L, D, P, Id, Params, + Expansions.size(), Expansions.data()); } TemplateTemplateParmDecl * TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTemplateParmDecl)); - return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, false, - 0, 0); + return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, + false, nullptr, nullptr); } TemplateTemplateParmDecl * TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumExpansions) { - unsigned Size = sizeof(TemplateTemplateParmDecl) + - sizeof(TemplateParameterList*) * NumExpansions; - void *Mem = AllocateDeserializedDecl(C, ID, Size); - return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, 0, 0, - NumExpansions, 0); + return new (C, ID, sizeof(TemplateParameterList*) * NumExpansions) + TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr, + nullptr, NumExpansions, nullptr); } //===----------------------------------------------------------------------===// @@ -682,7 +666,7 @@ FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD, const TemplateArgumentList *TemplateArgs, const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI) { - const ASTTemplateArgumentListInfo *ArgsAsWritten = 0; + const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; if (TemplateArgsAsWritten) ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C, *TemplateArgsAsWritten); @@ -710,20 +694,20 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, const TemplateArgument *Args, unsigned NumArgs, ClassTemplateSpecializationDecl *PrevDecl) - : CXXRecordDecl(DK, TK, DC, StartLoc, IdLoc, + : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc, SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), - ExplicitInfo(0), + ExplicitInfo(nullptr), TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)), SpecializationKind(TSK_Undeclared) { } -ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(Kind DK) - : CXXRecordDecl(DK, TTK_Struct, 0, SourceLocation(), SourceLocation(), 0, 0), - ExplicitInfo(0), - SpecializationKind(TSK_Undeclared) { -} +ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, + Kind DK) + : CXXRecordDecl(DK, TTK_Struct, C, nullptr, SourceLocation(), + SourceLocation(), nullptr, nullptr), + ExplicitInfo(nullptr), SpecializationKind(TSK_Undeclared) {} ClassTemplateSpecializationDecl * ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, @@ -734,13 +718,10 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, const TemplateArgument *Args, unsigned NumArgs, ClassTemplateSpecializationDecl *PrevDecl) { - ClassTemplateSpecializationDecl *Result - = new (Context)ClassTemplateSpecializationDecl(Context, - ClassTemplateSpecialization, - TK, DC, StartLoc, IdLoc, - SpecializedTemplate, - Args, NumArgs, - PrevDecl); + ClassTemplateSpecializationDecl *Result = + new (Context, DC) ClassTemplateSpecializationDecl( + Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc, + SpecializedTemplate, Args, NumArgs, PrevDecl); Result->MayHaveOutOfDateDef = false; Context.getTypeDeclType(Result, PrevDecl); @@ -748,12 +729,10 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, } ClassTemplateSpecializationDecl * -ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, +ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, - sizeof(ClassTemplateSpecializationDecl)); ClassTemplateSpecializationDecl *Result = - new (Mem) ClassTemplateSpecializationDecl(ClassTemplateSpecialization); + new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization); Result->MayHaveOutOfDateDef = false; return Result; } @@ -797,7 +776,7 @@ ClassTemplateSpecializationDecl::getSourceRange() const { typedef ClassTemplatePartialSpecializationDecl CTPSDecl; CTPSDecl *ctpsd = const_cast<CTPSDecl*>(cast<CTPSDecl>(this)); CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember(); - assert(inst_from != 0); + assert(inst_from != nullptr); return inst_from->getSourceRange(); } else { @@ -836,7 +815,7 @@ ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, SpecializedTemplate, Args, NumArgs, PrevDecl), TemplateParams(Params), ArgsAsWritten(ArgInfos), - InstantiatedFromMember(0, false) + InstantiatedFromMember(nullptr, false) { AdoptTemplateParameterList(Params, this); } @@ -855,14 +834,10 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, const ASTTemplateArgumentListInfo *ASTArgInfos = ASTTemplateArgumentListInfo::Create(Context, ArgInfos); - ClassTemplatePartialSpecializationDecl *Result - = new (Context)ClassTemplatePartialSpecializationDecl(Context, TK, DC, - StartLoc, IdLoc, - Params, - SpecializedTemplate, - Args, NumArgs, - ASTArgInfos, - PrevDecl); + ClassTemplatePartialSpecializationDecl *Result = new (Context, DC) + ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc, + Params, SpecializedTemplate, Args, + NumArgs, ASTArgInfos, PrevDecl); Result->setSpecializationKind(TSK_ExplicitSpecialization); Result->MayHaveOutOfDateDef = false; @@ -873,10 +848,8 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, ClassTemplatePartialSpecializationDecl * ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, - sizeof(ClassTemplatePartialSpecializationDecl)); - ClassTemplatePartialSpecializationDecl *Result - = new (Mem) ClassTemplatePartialSpecializationDecl(); + ClassTemplatePartialSpecializationDecl *Result = + new (C, ID) ClassTemplatePartialSpecializationDecl(C); Result->MayHaveOutOfDateDef = false; return Result; } @@ -894,15 +867,13 @@ FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context, TemplateParameterList **Params, FriendUnion Friend, SourceLocation FLoc) { - FriendTemplateDecl *Result - = new (Context) FriendTemplateDecl(DC, L, NParams, Params, Friend, FLoc); - return Result; + return new (Context, DC) FriendTemplateDecl(DC, L, NParams, Params, + Friend, FLoc); } FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FriendTemplateDecl)); - return new (Mem) FriendTemplateDecl(EmptyShell()); + return new (C, ID) FriendTemplateDecl(EmptyShell()); } //===----------------------------------------------------------------------===// @@ -916,14 +887,13 @@ TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C, TemplateParameterList *Params, NamedDecl *Decl) { AdoptTemplateParameterList(Params, DC); - return new (C) TypeAliasTemplateDecl(DC, L, Name, Params, Decl); + return new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl); } TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypeAliasTemplateDecl)); - return new (Mem) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(), - 0, 0); + return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(), + DeclarationName(), nullptr, nullptr); } void TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) { @@ -945,10 +915,8 @@ void ClassScopeFunctionSpecializationDecl::anchor() { } ClassScopeFunctionSpecializationDecl * ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, - sizeof(ClassScopeFunctionSpecializationDecl)); - return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0, - false, TemplateArgumentListInfo()); + return new (C, ID) ClassScopeFunctionSpecializationDecl( + nullptr, SourceLocation(), nullptr, false, TemplateArgumentListInfo()); } //===----------------------------------------------------------------------===// @@ -966,33 +934,30 @@ VarTemplateDecl *VarTemplateDecl::getDefinition() { return CurD; CurD = CurD->getPreviousDecl(); } - return 0; + return nullptr; } VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl, - VarTemplateDecl *PrevDecl) { - VarTemplateDecl *New = new (C) VarTemplateDecl(DC, L, Name, Params, Decl); - New->setPreviousDecl(PrevDecl); - return New; + VarDecl *Decl) { + return new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl); } VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarTemplateDecl)); - return new (Mem) VarTemplateDecl(EmptyShell()); + return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(), + DeclarationName(), nullptr, nullptr); } -// TODO: Unify accross class, function and variable templates? +// TODO: Unify across class, function and variable templates? // May require moving this and Common to RedeclarableTemplateDecl. void VarTemplateDecl::LoadLazySpecializations() const { Common *CommonPtr = getCommonPtr(); if (CommonPtr->LazySpecializations) { ASTContext &Context = getASTContext(); uint32_t *Specs = CommonPtr->LazySpecializations; - CommonPtr->LazySpecializations = 0; + CommonPtr->LazySpecializations = nullptr; for (uint32_t I = 0, N = *Specs++; I != N; ++I) (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); } @@ -1018,9 +983,9 @@ VarTemplateDecl::newCommon(ASTContext &C) const { } VarTemplateSpecializationDecl * -VarTemplateDecl::findSpecialization(const TemplateArgument *Args, - unsigned NumArgs, void *&InsertPos) { - return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos); +VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, + void *&InsertPos) { + return findSpecializationImpl(getSpecializations(), Args, InsertPos); } void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D, @@ -1038,10 +1003,9 @@ void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D, } VarTemplatePartialSpecializationDecl * -VarTemplateDecl::findPartialSpecialization(const TemplateArgument *Args, - unsigned NumArgs, void *&InsertPos) { - return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs, - InsertPos); +VarTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args, + void *&InsertPos) { + return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos); } void VarTemplateDecl::AddPartialSpecialization( @@ -1084,47 +1048,43 @@ VarTemplateDecl::findPartialSpecInstantiatedFromMember( return P->getMostRecentDecl(); } - return 0; + return nullptr; } //===----------------------------------------------------------------------===// // VarTemplateSpecializationDecl Implementation //===----------------------------------------------------------------------===// VarTemplateSpecializationDecl::VarTemplateSpecializationDecl( - ASTContext &Context, Kind DK, DeclContext *DC, SourceLocation StartLoc, + Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, unsigned NumArgs) - : VarDecl(DK, DC, StartLoc, IdLoc, SpecializedTemplate->getIdentifier(), T, - TInfo, S), - SpecializedTemplate(SpecializedTemplate), ExplicitInfo(0), + : VarDecl(DK, Context, DC, StartLoc, IdLoc, + SpecializedTemplate->getIdentifier(), T, TInfo, S), + SpecializedTemplate(SpecializedTemplate), ExplicitInfo(nullptr), TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)), SpecializationKind(TSK_Undeclared) {} -VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK) - : VarDecl(DK, 0, SourceLocation(), SourceLocation(), 0, QualType(), 0, - SC_None), - ExplicitInfo(0), SpecializationKind(TSK_Undeclared) {} +VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK, + ASTContext &C) + : VarDecl(DK, C, nullptr, SourceLocation(), SourceLocation(), nullptr, + QualType(), nullptr, SC_None), + ExplicitInfo(nullptr), SpecializationKind(TSK_Undeclared) {} VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, unsigned NumArgs) { - VarTemplateSpecializationDecl *Result = new (Context) - VarTemplateSpecializationDecl(Context, VarTemplateSpecialization, DC, - StartLoc, IdLoc, SpecializedTemplate, T, - TInfo, S, Args, NumArgs); - return Result; + return new (Context, DC) VarTemplateSpecializationDecl( + VarTemplateSpecialization, Context, DC, StartLoc, IdLoc, + SpecializedTemplate, T, TInfo, S, Args, NumArgs); } VarTemplateSpecializationDecl * VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = - AllocateDeserializedDecl(C, ID, sizeof(VarTemplateSpecializationDecl)); - VarTemplateSpecializationDecl *Result = - new (Mem) VarTemplateSpecializationDecl(VarTemplateSpecialization); - return Result; + return new (C, ID) + VarTemplateSpecializationDecl(VarTemplateSpecialization, C); } void VarTemplateSpecializationDecl::getNameForDiagnostic( @@ -1163,11 +1123,11 @@ VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl( VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, unsigned NumArgs, const ASTTemplateArgumentListInfo *ArgInfos) - : VarTemplateSpecializationDecl(Context, VarTemplatePartialSpecialization, + : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context, DC, StartLoc, IdLoc, SpecializedTemplate, T, TInfo, S, Args, NumArgs), TemplateParams(Params), ArgsAsWritten(ArgInfos), - InstantiatedFromMember(0, false) { + InstantiatedFromMember(nullptr, false) { // TODO: The template parameters should be in DC by now. Verify. // AdoptTemplateParameterList(Params, DC); } @@ -1183,7 +1143,7 @@ VarTemplatePartialSpecializationDecl::Create( = ASTTemplateArgumentListInfo::Create(Context, ArgInfos); VarTemplatePartialSpecializationDecl *Result = - new (Context) VarTemplatePartialSpecializationDecl( + new (Context, DC) VarTemplatePartialSpecializationDecl( Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, S, Args, NumArgs, ASTArgInfos); Result->setSpecializationKind(TSK_ExplicitSpecialization); @@ -1193,9 +1153,5 @@ VarTemplatePartialSpecializationDecl::Create( VarTemplatePartialSpecializationDecl * VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl( - C, ID, sizeof(VarTemplatePartialSpecializationDecl)); - VarTemplatePartialSpecializationDecl *Result = - new (Mem) VarTemplatePartialSpecializationDecl(); - return Result; + return new (C, ID) VarTemplatePartialSpecializationDecl(C); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp index e064e23..b7c2877 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp @@ -143,13 +143,16 @@ raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - return OS << N.getObjCSelector().getAsString(); + N.getObjCSelector().print(OS); + return OS; case DeclarationName::CXXConstructorName: { QualType ClassType = N.getCXXNameType(); if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) return OS << *ClassRec->getDecl(); - return OS << ClassType.getAsString(); + LangOptions LO; + LO.CPlusPlus = true; + return OS << ClassType.getAsString(PrintingPolicy(LO)); } case DeclarationName::CXXDestructorName: { @@ -157,12 +160,14 @@ raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { QualType Type = N.getCXXNameType(); if (const RecordType *Rec = Type->getAs<RecordType>()) return OS << *Rec->getDecl(); - return OS << Type.getAsString(); + LangOptions LO; + LO.CPlusPlus = true; + return OS << Type.getAsString(PrintingPolicy(LO)); } case DeclarationName::CXXOperatorName: { static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = { - 0, + nullptr, #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ Spelling, #include "clang/Basic/OperatorKinds.def" @@ -184,7 +189,10 @@ raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { QualType Type = N.getCXXNameType(); if (const RecordType *Rec = Type->getAs<RecordType>()) return OS << *Rec->getDecl(); - return OS << Type.getAsString(); + LangOptions LO; + LO.CPlusPlus = true; + LO.Bool = true; + return OS << Type.getAsString(PrintingPolicy(LO)); } case DeclarationName::CXXUsingDirective: return OS << "<using-directive>"; @@ -265,7 +273,7 @@ IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const { if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName()) return CXXLit->ID; else - return 0; + return nullptr; } void *DeclarationName::getFETokenInfoAsVoidSlow() const { @@ -338,7 +346,7 @@ DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) { for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) { CXXOperatorNames[Op].ExtraKindOrNumArgs = Op + DeclarationNameExtra::CXXConversionFunction; - CXXOperatorNames[Op].FETokenInfo = 0; + CXXOperatorNames[Op].FETokenInfo = nullptr; } } @@ -399,14 +407,14 @@ DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, ID.AddInteger(EKind); ID.AddPointer(Ty.getAsOpaquePtr()); - void *InsertPos = 0; + void *InsertPos = nullptr; if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos)) return DeclarationName(Name); CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName; SpecialName->ExtraKindOrNumArgs = EKind; SpecialName->Type = Ty; - SpecialName->FETokenInfo = 0; + SpecialName->FETokenInfo = nullptr; SpecialNames->InsertNode(SpecialName, InsertPos); return DeclarationName(SpecialName); @@ -426,7 +434,7 @@ DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { llvm::FoldingSetNodeID ID; ID.AddPointer(II); - void *InsertPos = 0; + void *InsertPos = nullptr; if (CXXLiteralOperatorIdName *Name = LiteralNames->FindNodeOrInsertPos(ID, InsertPos)) return DeclarationName (Name); @@ -434,7 +442,7 @@ DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName; LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator; LiteralName->ID = II; - LiteralName->FETokenInfo = 0; + LiteralName->FETokenInfo = nullptr; LiteralNames->InsertNode(LiteralName, InsertPos); return DeclarationName(LiteralName); @@ -447,7 +455,7 @@ DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) { case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: - NamedType.TInfo = 0; + NamedType.TInfo = nullptr; break; case DeclarationName::CXXOperatorName: CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding(); @@ -537,7 +545,10 @@ void DeclarationNameInfo::printName(raw_ostream &OS) const { OS << '~'; else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) OS << "operator "; - OS << TInfo->getType().getAsString(); + LangOptions LO; + LO.CPlusPlus = true; + LO.Bool = true; + OS << TInfo->getType().getAsString(PrintingPolicy(LO)); } else OS << Name; return; diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 9055ddac..5f559b7 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -44,7 +44,7 @@ const CXXRecordDecl *Expr::getBestDynamicClassType() const { DerivedType = PTy->getPointeeType(); if (DerivedType->isDependentType()) - return NULL; + return nullptr; const RecordType *Ty = DerivedType->castAs<RecordType>(); Decl *D = Ty->getDecl(); @@ -105,37 +105,6 @@ const Expr *Expr::skipRValueSubobjectAdjustments( return E; } -const Expr * -Expr::findMaterializedTemporary(const MaterializeTemporaryExpr *&MTE) const { - const Expr *E = this; - - // This might be a default initializer for a reference member. Walk over the - // wrapper node for that. - if (const CXXDefaultInitExpr *DAE = dyn_cast<CXXDefaultInitExpr>(E)) - E = DAE->getExpr(); - - // Look through single-element init lists that claim to be lvalues. They're - // just syntactic wrappers in this case. - if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E)) { - if (ILE->getNumInits() == 1 && ILE->isGLValue()) { - E = ILE->getInit(0); - if (const CXXDefaultInitExpr *DAE = dyn_cast<CXXDefaultInitExpr>(E)) - E = DAE->getExpr(); - } - } - - // Look through expressions for materialized temporaries (for now). - if (const MaterializeTemporaryExpr *M - = dyn_cast<MaterializeTemporaryExpr>(E)) { - MTE = M; - E = M->GetTemporaryExpr(); - } - - if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E)) - E = DAE->getExpr(); - return E; -} - /// isKnownToHaveBooleanValue - Return true if this is an integer expression /// that is known to return 0 or 1. This happens for _Bool/bool expressions /// but also int expressions which are produced by things like comparisons in @@ -152,6 +121,8 @@ bool Expr::isKnownToHaveBooleanValue() const { switch (UO->getOpcode()) { case UO_Plus: return UO->getSubExpr()->isKnownToHaveBooleanValue(); + case UO_LNot: + return true; default: return false; } @@ -431,7 +402,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, const TemplateArgumentListInfo *TemplateArgs) { // Filter out cases where the found Decl is the same as the value refenenced. if (D == FoundD) - FoundD = 0; + FoundD = nullptr; std::size_t Size = sizeof(DeclRefExpr); if (QualifierLoc) @@ -484,7 +455,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { if (IT == PredefinedExpr::FuncDName) { if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurrentDecl)) { - OwningPtr<MangleContext> MC; + std::unique_ptr<MangleContext> MC; MC.reset(Context.createMangleContext()); if (MC->shouldMangleDeclName(ND)) { @@ -507,7 +478,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { return ""; } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) { - if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual) + if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig) return FD->getNameAsString(); SmallString<256> Name; @@ -523,16 +494,28 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { PrintingPolicy Policy(Context.getLangOpts()); std::string Proto; llvm::raw_string_ostream POut(Proto); - FD->printQualifiedName(POut, Policy); const FunctionDecl *Decl = FD; if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern()) Decl = Pattern; const FunctionType *AFT = Decl->getType()->getAs<FunctionType>(); - const FunctionProtoType *FT = 0; + const FunctionProtoType *FT = nullptr; if (FD->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(AFT); + if (IT == FuncSig) { + switch (FT->getCallConv()) { + case CC_C: POut << "__cdecl "; break; + case CC_X86StdCall: POut << "__stdcall "; break; + case CC_X86FastCall: POut << "__fastcall "; break; + case CC_X86ThisCall: POut << "__thiscall "; break; + // Only bother printing the conventions that MSVC knows about. + default: break; + } + } + + FD->printQualifiedName(POut, Policy); + POut << "("; if (FT) { for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) { @@ -619,13 +602,15 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { // not a constructor or destructor. if ((isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->getParent()->isLambda()) || - (FT && FT->getResultType()->getAs<AutoType>())) + (FT && FT->getReturnType()->getAs<AutoType>())) Proto = "auto " + Proto; - else if (FT && FT->getResultType()->getAs<DecltypeType>()) - FT->getResultType()->getAs<DecltypeType>()->getUnderlyingType() + else if (FT && FT->getReturnType()->getAs<DecltypeType>()) + FT->getReturnType() + ->getAs<DecltypeType>() + ->getUnderlyingType() .getAsStringInternal(Proto, Policy); else if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD)) - AFT->getResultType().getAsStringInternal(Proto, Policy); + AFT->getReturnType().getAsStringInternal(Proto, Policy); Out << Proto; @@ -658,7 +643,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { Out << '(' << *CID << ')'; Out << ' '; - Out << MD->getSelector().getAsString(); + MD->getSelector().print(Out); Out << ']'; Out.flush(); @@ -810,6 +795,9 @@ StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str, StringKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumStrs) { + assert(C.getAsConstantArrayType(Ty) && + "StringLiteral must be of constant array type!"); + // Allocate enough space for the StringLiteral plus an array of locations for // any concatenated string tokens. void *Mem = C.Allocate(sizeof(StringLiteral)+ @@ -1010,7 +998,7 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM, TheLexer.LexFromRawLexer(TheTok); // Use the StringLiteralParser to compute the length of the string in bytes. - StringLiteralParser SLP(&TheTok, 1, SM, Features, Target); + StringLiteralParser SLP(TheTok, SM, Features, Target); unsigned TokNumBytes = SLP.GetStringLength(); // If the byte is in this token, return the location of the byte. @@ -1144,7 +1132,7 @@ CallExpr::CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, } CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), SubExprs(0), NumArgs(0) { + : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) { // FIXME: Why do we allocate this? SubExprs = new (C) Stmt*[PREARGS_START]; CallExprBits.NumPreArgs = 0; @@ -1152,7 +1140,7 @@ CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty) CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty) - : Expr(SC, Empty), SubExprs(0), NumArgs(0) { + : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) { // FIXME: Why do we allocate this? SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs]; CallExprBits.NumPreArgs = NumPreArgs; @@ -1179,7 +1167,7 @@ Decl *CallExpr::getCalleeDecl() { if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE)) return ME->getMemberDecl(); - return 0; + return nullptr; } FunctionDecl *CallExpr::getDirectCallee() { @@ -1208,16 +1196,16 @@ void CallExpr::setNumArgs(const ASTContext& C, unsigned NumArgs) { // Null out new args. for (unsigned i = getNumArgs()+PREARGS_START+NumPreArgs; i != NumArgs+PREARGS_START+NumPreArgs; ++i) - NewSubExprs[i] = 0; + NewSubExprs[i] = nullptr; if (SubExprs) C.Deallocate(SubExprs); SubExprs = NewSubExprs; this->NumArgs = NumArgs; } -/// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If +/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID. If /// not, return 0. -unsigned CallExpr::isBuiltinCall() const { +unsigned CallExpr::getBuiltinCallee() const { // All simple function calls (e.g. func()) are implicitly cast to pointer to // function. As a result, we try and obtain the DeclRefExpr from the // ImplicitCastExpr. @@ -1240,7 +1228,7 @@ unsigned CallExpr::isBuiltinCall() const { } bool CallExpr::isUnevaluatedBuiltinCall(ASTContext &Ctx) const { - if (unsigned BI = isBuiltinCall()) + if (unsigned BI = getBuiltinCallee()) return Ctx.BuiltinInfo.isUnevaluated(BI); return false; } @@ -1256,7 +1244,7 @@ QualType CallExpr::getCallReturnType() const { CalleeType = Expr::findBoundMemberType(getCallee()); const FunctionType *FnType = CalleeType->castAs<FunctionType>(); - return FnType->getResultType(); + return FnType->getReturnType(); } SourceLocation CallExpr::getLocStart() const { @@ -1421,7 +1409,7 @@ SourceLocation MemberExpr::getLocEnd() const { return EndLoc; } -void CastExpr::CheckCastConsistency() const { +bool CastExpr::CastConsistency() const { switch (getCastKind()) { case CK_DerivedToBase: case CK_UncheckedDerivedToBase: @@ -1474,6 +1462,11 @@ void CastExpr::CheckCastConsistency() const { assert(getSubExpr()->getType()->isFunctionType()); goto CheckNoBasePath; + case CK_AddressSpaceConversion: + assert(getType()->isPointerType()); + assert(getSubExpr()->getType()->isPointerType()); + assert(getType()->getPointeeType().getAddressSpace() != + getSubExpr()->getType()->getPointeeType().getAddressSpace()); // These should not have an inheritance path. case CK_Dynamic: case CK_ToUnion: @@ -1524,6 +1517,7 @@ void CastExpr::CheckCastConsistency() const { assert(path_empty() && "Cast kind should not have a base path!"); break; } + return true; } const char *CastExpr::getCastKindName() const { @@ -1625,7 +1619,7 @@ const char *CastExpr::getCastKindName() const { case CK_ARCReclaimReturnedObject: return "ARCReclaimReturnedObject"; case CK_ARCExtendBlockObject: - return "ARCCExtendBlockObject"; + return "ARCExtendBlockObject"; case CK_AtomicToNonAtomic: return "AtomicToNonAtomic"; case CK_NonAtomicToAtomic: @@ -1636,13 +1630,15 @@ const char *CastExpr::getCastKindName() const { return "BuiltinFnToFnPtr"; case CK_ZeroToOCLEvent: return "ZeroToOCLEvent"; + case CK_AddressSpaceConversion: + return "AddressSpaceConversion"; } llvm_unreachable("Unhandled cast kind!"); } Expr *CastExpr::getSubExprAsWritten() { - Expr *SubExpr = 0; + Expr *SubExpr = nullptr; CastExpr *E = this; do { SubExpr = E->getSubExpr(); @@ -1838,7 +1834,7 @@ InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc, : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, false, false), InitExprs(C, initExprs.size()), - LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(0, true) + LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(nullptr, true) { sawArrayRangeDesignator(false); for (unsigned I = 0; I != initExprs.size(); ++I) { @@ -1861,18 +1857,18 @@ void InitListExpr::reserveInits(const ASTContext &C, unsigned NumInits) { } void InitListExpr::resizeInits(const ASTContext &C, unsigned NumInits) { - InitExprs.resize(C, NumInits, 0); + InitExprs.resize(C, NumInits, nullptr); } Expr *InitListExpr::updateInit(const ASTContext &C, unsigned Init, Expr *expr) { if (Init >= InitExprs.size()) { - InitExprs.insert(C, InitExprs.end(), Init - InitExprs.size() + 1, 0); - InitExprs.back() = expr; - return 0; + InitExprs.insert(C, InitExprs.end(), Init - InitExprs.size() + 1, nullptr); + setInit(Init, expr); + return nullptr; } Expr *Result = cast_or_null<Expr>(InitExprs[Init]); - InitExprs[Init] = expr; + setInit(Init, expr); return Result; } @@ -1882,7 +1878,7 @@ void InitListExpr::setArrayFiller(Expr *filler) { // Fill out any "holes" in the array due to designated initializers. Expr **inits = getInits(); for (unsigned i = 0, e = getNumInits(); i != e; ++i) - if (inits[i] == 0) + if (inits[i] == nullptr) inits[i] = filler; } @@ -1892,7 +1888,11 @@ bool InitListExpr::isStringLiteralInit() const { const ArrayType *AT = getType()->getAsArrayTypeUnsafe(); if (!AT || !AT->getElementType()->isIntegerType()) return false; - const Expr *Init = getInit(0)->IgnoreParens(); + // It is possible for getInit() to return null. + const Expr *Init = getInit(0); + if (!Init) + return false; + Init = Init->IgnoreParens(); return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init); } @@ -2078,15 +2078,25 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, return true; case CXXOperatorCallExprClass: { - // We warn about operator== and operator!= even when user-defined operator + // Warn about operator ==,!=,<,>,<=, and >= even when user-defined operator // overloads as there is no reasonable way to define these such that they // have non-trivial, desirable side-effects. See the -Wunused-comparison - // warning: these operators are commonly typo'ed, and so warning on them + // warning: operators == and != are commonly typo'ed, and so warning on them // provides additional value as well. If this list is updated, // DiagnoseUnusedComparison should be as well. const CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(this); - if (Op->getOperator() == OO_EqualEqual || - Op->getOperator() == OO_ExclaimEqual) { + switch (Op->getOperator()) { + default: + break; + case OO_EqualEqual: + case OO_ExclaimEqual: + case OO_Less: + case OO_Greater: + case OO_GreaterEqual: + case OO_LessEqual: + if (Op->getCallReturnType()->isReferenceType() || + Op->getCallReturnType()->isVoidType()) + break; WarnE = this; Loc = Op->getOperatorLoc(); R1 = Op->getSourceRange(); @@ -2106,8 +2116,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, // // Note: If new cases are added here, DiagnoseUnusedExprResult should be // updated to match for QoI. - if (FD->getAttr<WarnUnusedResultAttr>() || - FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) { + if (FD->hasAttr<WarnUnusedResultAttr>() || + FD->hasAttr<PureAttr>() || FD->hasAttr<ConstAttr>()) { WarnE = this; Loc = CE->getCallee()->getLocStart(); R1 = CE->getCallee()->getSourceRange(); @@ -2151,12 +2161,15 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, return true; } - const ObjCMethodDecl *MD = ME->getMethodDecl(); - if (MD && MD->getAttr<WarnUnusedResultAttr>()) { - WarnE = this; - Loc = getExprLoc(); - return true; - } + if (const ObjCMethodDecl *MD = ME->getMethodDecl()) + if (MD->hasAttr<WarnUnusedResultAttr>() || + (MD->isPropertyAccessor() && !MD->getReturnType()->isVoidType() && + !ME->getReceiverType()->isObjCIdType())) { + WarnE = this; + Loc = getExprLoc(); + return true; + } + return false; } @@ -2393,6 +2406,27 @@ Expr *Expr::IgnoreParenCasts() { } } +Expr *Expr::IgnoreCasts() { + Expr *E = this; + while (true) { + if (CastExpr *P = dyn_cast<CastExpr>(E)) { + E = P->getSubExpr(); + continue; + } + if (MaterializeTemporaryExpr *Materialize + = dyn_cast<MaterializeTemporaryExpr>(E)) { + E = Materialize->GetTemporaryExpr(); + continue; + } + if (SubstNonTypeTemplateParmExpr *NTTP + = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { + E = NTTP->getReplacement(); + continue; + } + return E; + } +} + /// IgnoreParenLValueCasts - Ignore parentheses and lvalue-to-rvalue /// casts. This is intended purely as a temporary workaround for code /// that hasn't yet been rewritten to do the right thing about those @@ -2638,7 +2672,8 @@ bool Expr::hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs) { return false; } -bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { +bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, + const Expr **Culprit) const { // This function is attempting whether an expression is an initializer // which can be evaluated at compile-time. It very closely parallels // ConstExprEmitter in CGExprConstant.cpp; if they don't match, it @@ -2650,7 +2685,11 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { if (IsForRef) { EvalResult Result; - return EvaluateAsLValue(Result, Ctx) && !Result.HasSideEffects; + if (EvaluateAsLValue(Result, Ctx) && !Result.HasSideEffects) + return true; + if (Culprit) + *Culprit = this; + return false; } switch (getStmtClass()) { @@ -2669,7 +2708,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { // Trivial copy constructor assert(CE->getNumArgs() == 1 && "trivial ctor with > 1 argument"); - return CE->getArg(0)->isConstantInitializer(Ctx, false); + return CE->getArg(0)->isConstantInitializer(Ctx, false, Culprit); } break; @@ -2679,14 +2718,14 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { // "struct x {int x;} x = (struct x) {};". // FIXME: This accepts other cases it shouldn't! const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer(); - return Exp->isConstantInitializer(Ctx, false); + return Exp->isConstantInitializer(Ctx, false, Culprit); } case InitListExprClass: { const InitListExpr *ILE = cast<InitListExpr>(this); if (ILE->getType()->isArrayType()) { unsigned numInits = ILE->getNumInits(); for (unsigned i = 0; i < numInits; i++) { - if (!ILE->getInit(i)->isConstantInitializer(Ctx, false)) + if (!ILE->getInit(i)->isConstantInitializer(Ctx, false, Culprit)) return false; } return true; @@ -2710,11 +2749,14 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { if (Field->isBitField()) { // Bitfields have to evaluate to an integer. llvm::APSInt ResultTmp; - if (!Elt->EvaluateAsInt(ResultTmp, Ctx)) + if (!Elt->EvaluateAsInt(ResultTmp, Ctx)) { + if (Culprit) + *Culprit = Elt; return false; + } } else { bool RefType = Field->getType()->isReferenceType(); - if (!Elt->isConstantInitializer(Ctx, RefType)) + if (!Elt->isConstantInitializer(Ctx, RefType, Culprit)) return false; } } @@ -2728,19 +2770,22 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { return true; case ParenExprClass: return cast<ParenExpr>(this)->getSubExpr() - ->isConstantInitializer(Ctx, IsForRef); + ->isConstantInitializer(Ctx, IsForRef, Culprit); case GenericSelectionExprClass: return cast<GenericSelectionExpr>(this)->getResultExpr() - ->isConstantInitializer(Ctx, IsForRef); + ->isConstantInitializer(Ctx, IsForRef, Culprit); case ChooseExprClass: - if (cast<ChooseExpr>(this)->isConditionDependent()) + if (cast<ChooseExpr>(this)->isConditionDependent()) { + if (Culprit) + *Culprit = this; return false; + } return cast<ChooseExpr>(this)->getChosenSubExpr() - ->isConstantInitializer(Ctx, IsForRef); + ->isConstantInitializer(Ctx, IsForRef, Culprit); case UnaryOperatorClass: { const UnaryOperator* Exp = cast<UnaryOperator>(this); if (Exp->getOpcode() == UO_Extension) - return Exp->getSubExpr()->isConstantInitializer(Ctx, false); + return Exp->getSubExpr()->isConstantInitializer(Ctx, false, Culprit); break; } case CXXFunctionalCastExprClass: @@ -2760,25 +2805,29 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { CE->getCastKind() == CK_ConstructorConversion || CE->getCastKind() == CK_NonAtomicToAtomic || CE->getCastKind() == CK_AtomicToNonAtomic) - return CE->getSubExpr()->isConstantInitializer(Ctx, false); + return CE->getSubExpr()->isConstantInitializer(Ctx, false, Culprit); break; } case MaterializeTemporaryExprClass: return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() - ->isConstantInitializer(Ctx, false); + ->isConstantInitializer(Ctx, false, Culprit); case SubstNonTypeTemplateParmExprClass: return cast<SubstNonTypeTemplateParmExpr>(this)->getReplacement() - ->isConstantInitializer(Ctx, false); + ->isConstantInitializer(Ctx, false, Culprit); case CXXDefaultArgExprClass: return cast<CXXDefaultArgExpr>(this)->getExpr() - ->isConstantInitializer(Ctx, false); + ->isConstantInitializer(Ctx, false, Culprit); case CXXDefaultInitExprClass: return cast<CXXDefaultInitExpr>(this)->getExpr() - ->isConstantInitializer(Ctx, false); + ->isConstantInitializer(Ctx, false, Culprit); } - return isEvaluatable(Ctx); + if (isEvaluatable(Ctx)) + return true; + if (Culprit) + *Culprit = this; + return false; } bool Expr::HasSideEffects(const ASTContext &Ctx) const { @@ -2821,8 +2870,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const { case CXXThisExprClass: case CXXScalarValueInitExprClass: case TypeTraitExprClass: - case UnaryTypeTraitExprClass: - case BinaryTypeTraitExprClass: case ArrayTypeTraitExprClass: case ExpressionTraitExprClass: case CXXNoexceptExprClass: @@ -3055,7 +3102,7 @@ Expr::NullPointerConstantKind Expr::isNullPointerConstant(ASTContext &Ctx, NullPointerConstantValueDependence NPC) const { if (isValueDependent() && - (!Ctx.getLangOpts().CPlusPlus11 || Ctx.getLangOpts().MicrosoftMode)) { + (!Ctx.getLangOpts().CPlusPlus11 || Ctx.getLangOpts().MSVCCompat)) { switch (NPC) { case NPC_NeverValueDependent: llvm_unreachable("Unexpected value dependent expression!"); @@ -3141,8 +3188,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx, const IntegerLiteral *Lit = dyn_cast<IntegerLiteral>(this); if (Lit && !Lit->getValue()) return NPCK_ZeroLiteral; - else if (!Ctx.getLangOpts().MicrosoftMode || - !isCXX98IntegralConstantExpr(Ctx)) + else if (!Ctx.getLangOpts().MSVCCompat || !isCXX98IntegralConstantExpr(Ctx)) return NPCK_NotNull; } else { // If we have an integer constant expression, we need to *evaluate* it and @@ -3233,7 +3279,7 @@ FieldDecl *Expr::getSourceBitField() { return BinOp->getRHS()->getSourceBitField(); } - return 0; + return nullptr; } bool Expr::refersToVectorElement() const { @@ -3339,8 +3385,9 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), Kind(IsInstanceSuper? SuperInstance : SuperClass), - HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit), - SuperLoc(SuperLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) + HasMethod(Method != nullptr), IsDelegateInitCall(false), + IsImplicit(isImplicit), SuperLoc(SuperLoc), LBracLoc(LBracLoc), + RBracLoc(RBracLoc) { initArgsAndSelLocs(Args, SelLocs, SelLocsK); setReceiverPointer(SuperType.getAsOpaquePtr()); @@ -3363,8 +3410,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), Kind(Class), - HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit), - LBracLoc(LBracLoc), RBracLoc(RBracLoc) + HasMethod(Method != nullptr), IsDelegateInitCall(false), + IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { initArgsAndSelLocs(Args, SelLocs, SelLocsK); setReceiverPointer(Receiver); @@ -3388,8 +3435,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), Kind(Instance), - HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit), - LBracLoc(LBracLoc), RBracLoc(RBracLoc) + HasMethod(Method != nullptr), IsDelegateInitCall(false), + IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { initArgsAndSelLocs(Args, SelLocs, SelLocsK); setReceiverPointer(Receiver); @@ -3571,7 +3618,7 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>()) return Ty->getInterface(); - return 0; + return nullptr; } StringRef ObjCBridgedCastExpr::getBridgeKindName() const { @@ -3806,30 +3853,21 @@ SourceLocation DesignatedInitExpr::getLocEnd() const { Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) const { assert(D.Kind == Designator::ArrayDesignator && "Requires array designator"); - char *Ptr = static_cast<char *>( - const_cast<void *>(static_cast<const void *>(this))); - Ptr += sizeof(DesignatedInitExpr); - Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr)); + Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1); return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1)); } Expr *DesignatedInitExpr::getArrayRangeStart(const Designator &D) const { assert(D.Kind == Designator::ArrayRangeDesignator && "Requires array range designator"); - char *Ptr = static_cast<char *>( - const_cast<void *>(static_cast<const void *>(this))); - Ptr += sizeof(DesignatedInitExpr); - Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr)); + Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1); return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1)); } Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator &D) const { assert(D.Kind == Designator::ArrayRangeDesignator && "Requires array range designator"); - char *Ptr = static_cast<char *>( - const_cast<void *>(static_cast<const void *>(this))); - Ptr += sizeof(DesignatedInitExpr); - Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr)); + Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1); return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2)); } @@ -3953,7 +3991,7 @@ PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK, ExprBits.ContainsUnexpandedParameterPack = true; if (isa<OpaqueValueExpr>(E)) - assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != 0 && + assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != nullptr && "opaque-value semantic expressions for pseudo-object " "operations must have sources"); } diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index 3738c0e..64c21dd 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -55,8 +55,8 @@ QualType CXXUuidofExpr::getTypeOperand(ASTContext &Context) const { } // static -UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT, - bool *RDHasMultipleGUIDsPtr) { +const UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT, + bool *RDHasMultipleGUIDsPtr) { // Optionally remove one level of pointer, reference or array indirection. const Type *Ty = QT.getTypePtr(); if (QT->isPointerType() || QT->isReferenceType()) @@ -64,22 +64,23 @@ UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT, else if (QT->isArrayType()) Ty = Ty->getBaseElementTypeUnsafe(); - // Loop all record redeclaration looking for an uuid attribute. - CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); if (!RD) - return 0; + return nullptr; + + if (const UuidAttr *Uuid = RD->getMostRecentDecl()->getAttr<UuidAttr>()) + return Uuid; // __uuidof can grab UUIDs from template arguments. - if (ClassTemplateSpecializationDecl *CTSD = + if (const ClassTemplateSpecializationDecl *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); - UuidAttr *UuidForRD = 0; + const UuidAttr *UuidForRD = nullptr; - for (unsigned I = 0, N = TAL.size(); I != N; ++I) { - const TemplateArgument &TA = TAL[I]; + for (const TemplateArgument &TA : TAL.asArray()) { bool SeenMultipleGUIDs = false; - UuidAttr *UuidForTA = 0; + const UuidAttr *UuidForTA = nullptr; if (TA.getKind() == TemplateArgument::Type) UuidForTA = GetUuidAttrOfType(TA.getAsType(), &SeenMultipleGUIDs); else if (TA.getKind() == TemplateArgument::Declaration) @@ -101,20 +102,14 @@ UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT, if (SeenMultipleGUIDs) { if (RDHasMultipleGUIDsPtr) *RDHasMultipleGUIDsPtr = true; - return 0; + return nullptr; } } return UuidForRD; } - for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(), - E = RD->redecls_end(); - I != E; ++I) - if (UuidAttr *Uuid = I->getAttr<UuidAttr>()) - return Uuid; - - return 0; + return nullptr; } StringRef CXXUuidofExpr::getUuidAsStringRef(ASTContext &Context) const { @@ -151,14 +146,15 @@ CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, ty->isDependentType(), ty->isDependentType(), ty->isInstantiationDependentType(), ty->containsUnexpandedParameterPack()), - SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), + SubExprs(nullptr), OperatorNew(operatorNew), OperatorDelete(operatorDelete), AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), Range(Range), DirectInitRange(directInitRange), GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { - assert((initializer != 0 || initializationStyle == NoInit) && + assert((initializer != nullptr || initializationStyle == NoInit) && "Only NoInit can have no initializer."); StoredInitializationStyle = initializer ? initializationStyle + 1 : 0; - AllocateArgsArray(C, arraySize != 0, placementArgs.size(), initializer != 0); + AllocateArgsArray(C, arraySize != nullptr, placementArgs.size(), + initializer != nullptr); unsigned i = 0; if (Array) { if (arraySize->isInstantiationDependent()) @@ -203,7 +199,7 @@ CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray, unsigned numPlaceArgs, bool hasInitializer){ - assert(SubExprs == 0 && "SubExprs already allocated"); + assert(SubExprs == nullptr && "SubExprs already allocated"); Array = isArray; NumPlacementArgs = numPlaceArgs; @@ -345,9 +341,9 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, QualifierLoc.getNestedNameSpecifier() ->containsUnexpandedParameterPack()))), NameInfo(NameInfo), QualifierLoc(QualifierLoc), - Results(0), NumResults(End - Begin), - HasTemplateKWAndArgsInfo(TemplateArgs != 0 || TemplateKWLoc.isValid()) -{ + Results(nullptr), NumResults(End - Begin), + HasTemplateKWAndArgsInfo(TemplateArgs != nullptr || + TemplateKWLoc.isValid()) { NumResults = End - Begin; if (NumResults) { // Determine whether this expression is type-dependent. @@ -398,7 +394,7 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, void OverloadExpr::initializeResults(const ASTContext &C, UnresolvedSetIterator Begin, UnresolvedSetIterator End) { - assert(Results == 0 && "Results already initialized!"); + assert(!Results && "Results already initialized!"); NumResults = End - Begin; if (NumResults) { Results = static_cast<DeclAccessPair *>( @@ -433,7 +429,7 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, QualifierLoc.getNestedNameSpecifier() ->containsUnexpandedParameterPack()))), QualifierLoc(QualifierLoc), NameInfo(NameInfo), - HasTemplateKWAndArgsInfo(Args != 0 || TemplateKWLoc.isValid()) + HasTemplateKWAndArgsInfo(Args != nullptr || TemplateKWLoc.isValid()) { if (Args) { bool Dependent = true; @@ -478,7 +474,7 @@ DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &C, DependentScopeDeclRefExpr *E = new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(), SourceLocation(), - DeclarationNameInfo(), 0); + DeclarationNameInfo(), nullptr); E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; } @@ -544,7 +540,7 @@ Expr *CXXMemberCallExpr::getImplicitObjectArgument() const { return BO->getLHS(); // FIXME: Will eventually need to cope with member pointers. - return 0; + return nullptr; } CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const { @@ -553,14 +549,14 @@ CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const { return cast<CXXMethodDecl>(MemExpr->getMemberDecl()); // FIXME: Will eventually need to cope with member pointers. - return 0; + return nullptr; } CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() const { Expr* ThisArg = getImplicitObjectArgument(); if (!ThisArg) - return 0; + return nullptr; if (ThisArg->getType()->isAnyPointerType()) return ThisArg->getType()->getPointeeType()->getAsCXXRecordDecl(); @@ -810,13 +806,16 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C, SourceRange ParenOrBraceRange, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization) : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type->getType().getNonReferenceType(), Type->getTypeLoc().getBeginLoc(), Cons, false, Args, HadMultipleCandidates, - ListInitialization, ZeroInitialization, + ListInitialization, + StdInitListInitialization, + ZeroInitialization, CXXConstructExpr::CK_Complete, ParenOrBraceRange), Type(Type) { } @@ -838,12 +837,14 @@ CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T, ArrayRef<Expr*> Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange) { return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, Elidable, Args, HadMultipleCandidates, ListInitialization, + StdInitListInitialization, ZeroInitialization, ConstructKind, ParenOrBraceRange); } @@ -854,6 +855,7 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, ArrayRef<Expr*> args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange) @@ -865,8 +867,9 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, NumArgs(args.size()), Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates), ListInitialization(ListInitialization), + StdInitListInitialization(StdInitListInitialization), ZeroInitialization(ZeroInitialization), - ConstructKind(ConstructKind), Args(0) + ConstructKind(ConstructKind), Args(nullptr) { if (NumArgs) { Args = new (C) Stmt*[args.size()]; @@ -886,7 +889,7 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, } } -LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit, +LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind, VarDecl *Var, SourceLocation EllipsisLoc) : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc) @@ -896,8 +899,8 @@ LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit, Bits |= Capture_Implicit; switch (Kind) { - case LCK_This: - assert(Var == 0 && "'this' capture cannot have a variable!"); + case LCK_This: + assert(!Var && "'this' capture cannot have a variable!"); break; case LCK_ByCopy: @@ -910,7 +913,7 @@ LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit, DeclAndBits.setInt(Bits); } -LambdaCaptureKind LambdaExpr::Capture::getCaptureKind() const { +LambdaCaptureKind LambdaCapture::getCaptureKind() const { Decl *D = DeclAndBits.getPointer(); if (!D) return LCK_This; @@ -1031,6 +1034,10 @@ LambdaExpr::capture_iterator LambdaExpr::capture_end() const { return capture_begin() + NumCaptures; } +LambdaExpr::capture_range LambdaExpr::captures() const { + return capture_range(capture_begin(), capture_end()); +} + LambdaExpr::capture_iterator LambdaExpr::explicit_capture_begin() const { return capture_begin(); } @@ -1041,6 +1048,10 @@ LambdaExpr::capture_iterator LambdaExpr::explicit_capture_end() const { return Data.Captures + Data.NumExplicitCaptures; } +LambdaExpr::capture_range LambdaExpr::explicit_captures() const { + return capture_range(explicit_capture_begin(), explicit_capture_end()); +} + LambdaExpr::capture_iterator LambdaExpr::implicit_capture_begin() const { return explicit_capture_end(); } @@ -1049,6 +1060,10 @@ LambdaExpr::capture_iterator LambdaExpr::implicit_capture_end() const { return capture_end(); } +LambdaExpr::capture_range LambdaExpr::implicit_captures() const { + return capture_range(implicit_capture_begin(), implicit_capture_end()); +} + ArrayRef<VarDecl *> LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const { assert(HasArrayIndexVars && "No array index-var data?"); @@ -1187,7 +1202,8 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(const ASTContext &C, ->containsUnexpandedParameterPack()) || MemberNameInfo.containsUnexpandedParameterPack())), Base(Base), BaseType(BaseType), IsArrow(IsArrow), - HasTemplateKWAndArgsInfo(TemplateArgs != 0 || TemplateKWLoc.isValid()), + HasTemplateKWAndArgsInfo(TemplateArgs != nullptr || + TemplateKWLoc.isValid()), OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), FirstQualifierFoundInScope(FirstQualifierFoundInScope), MemberNameInfo(MemberNameInfo) { @@ -1260,26 +1276,26 @@ CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { if (!HasTemplateKWAndArgsInfo) - return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(), + return new (C) CXXDependentScopeMemberExpr(C, nullptr, QualType(), 0, SourceLocation(), - NestedNameSpecifierLoc(), 0, - DeclarationNameInfo()); + NestedNameSpecifierLoc(), + nullptr, DeclarationNameInfo()); std::size_t size = sizeof(CXXDependentScopeMemberExpr) + ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>()); CXXDependentScopeMemberExpr *E - = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(), + = new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(), 0, SourceLocation(), NestedNameSpecifierLoc(), - SourceLocation(), 0, - DeclarationNameInfo(), 0); + SourceLocation(), nullptr, + DeclarationNameInfo(), nullptr); E->HasTemplateKWAndArgsInfo = true; return E; } bool CXXDependentScopeMemberExpr::isImplicitAccess() const { - if (Base == 0) + if (!Base) return true; return cast<Expr>(Base)->isImplicitCXXThis(); @@ -1291,16 +1307,11 @@ static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin, NamedDecl *decl = *begin; if (isa<UnresolvedUsingValueDecl>(decl)) return false; - if (isa<UsingShadowDecl>(decl)) - decl = cast<UsingShadowDecl>(decl)->getUnderlyingDecl(); // Unresolved member expressions should only contain methods and // method templates. - assert(isa<CXXMethodDecl>(decl) || isa<FunctionTemplateDecl>(decl)); - - if (isa<FunctionTemplateDecl>(decl)) - decl = cast<FunctionTemplateDecl>(decl)->getTemplatedDecl(); - if (cast<CXXMethodDecl>(decl)->isStatic()) + if (cast<CXXMethodDecl>(decl->getUnderlyingDecl()->getAsFunction()) + ->isStatic()) return false; } while (++begin != end); @@ -1338,7 +1349,7 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(const ASTContext &C, } bool UnresolvedMemberExpr::isImplicitAccess() const { - if (Base == 0) + if (!Base) return true; return cast<Expr>(Base)->isImplicitCXXThis(); @@ -1387,7 +1398,7 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { // If there was a nested name specifier, it names the naming class. // It can't be dependent: after all, we were actually able to do the // lookup. - CXXRecordDecl *Record = 0; + CXXRecordDecl *Record = nullptr; if (getQualifier()) { const Type *T = getQualifier()->getAsType(); assert(T && "qualifier in member expression does not name type"); @@ -1450,7 +1461,26 @@ FunctionParmPackExpr::CreateEmpty(const ASTContext &Context, unsigned NumParams) { return new (Context.Allocate(sizeof(FunctionParmPackExpr) + sizeof(ParmVarDecl*) * NumParams)) - FunctionParmPackExpr(QualType(), 0, SourceLocation(), 0, 0); + FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr); +} + +void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy, + unsigned ManglingNumber) { + // We only need extra state if we have to remember more than just the Stmt. + if (!ExtendedBy) + return; + + // We may need to allocate extra storage for the mangling number and the + // extended-by ValueDecl. + if (!State.is<ExtraState *>()) { + auto ES = new (ExtendedBy->getASTContext()) ExtraState; + ES->Temporary = State.get<Stmt *>(); + State = ES; + } + + auto ES = State.get<ExtraState *>(); + ES->ExtendingDecl = ExtendedBy; + ES->ManglingNumber = ManglingNumber; } TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index 54f77ef..d3d2530 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -165,8 +165,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::FloatingLiteralClass: case Expr::CXXNoexceptExprClass: case Expr::CXXScalarValueInitExprClass: - case Expr::UnaryTypeTraitExprClass: - case Expr::BinaryTypeTraitExprClass: case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: @@ -348,7 +346,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ObjCMessageExprClass: if (const ObjCMethodDecl *Method = cast<ObjCMessageExpr>(E)->getMethodDecl()) { - Cl::Kinds kind = ClassifyUnnamed(Ctx, Method->getResultType()); + Cl::Kinds kind = ClassifyUnnamed(Ctx, Method->getReturnType()); return (kind == Cl::CL_PRValue) ? Cl::CL_ObjCMessageRValue : kind; } return Cl::CL_PRValue; @@ -543,10 +541,21 @@ static Cl::Kinds ClassifyConditional(ASTContext &Ctx, const Expr *True, "This is only relevant for C++."); // C++ [expr.cond]p2 - // If either the second or the third operand has type (cv) void, [...] - // the result [...] is a prvalue. - if (True->getType()->isVoidType() || False->getType()->isVoidType()) + // If either the second or the third operand has type (cv) void, + // one of the following shall hold: + if (True->getType()->isVoidType() || False->getType()->isVoidType()) { + // The second or the third operand (but not both) is a (possibly + // parenthesized) throw-expression; the result is of the [...] value + // category of the other. + bool TrueIsThrow = isa<CXXThrowExpr>(True->IgnoreParenImpCasts()); + bool FalseIsThrow = isa<CXXThrowExpr>(False->IgnoreParenImpCasts()); + if (const Expr *NonThrow = TrueIsThrow ? (FalseIsThrow ? nullptr : False) + : (FalseIsThrow ? True : nullptr)) + return ClassifyInternal(Ctx, NonThrow); + + // [Otherwise] the result [...] is a prvalue. return Cl::CL_PRValue; + } // Note that at this point, we have already performed all conversions // according to [expr.cond]p3. @@ -584,7 +593,8 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, // Assignment to a property in ObjC is an implicit setter access. But a // setter might not exist. if (const ObjCPropertyRefExpr *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) { - if (Expr->isImplicitProperty() && Expr->getImplicitPropertySetter() == 0) + if (Expr->isImplicitProperty() && + Expr->getImplicitPropertySetter() == nullptr) return Cl::CM_NoSetterProperty; } diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 4cac4fa..7d7ca99 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -320,7 +320,7 @@ namespace { APValue *getTemporary(const void *Key) { MapTy::iterator I = Temporaries.find(Key); - return I == Temporaries.end() ? 0 : &I->second; + return I == Temporaries.end() ? nullptr : &I->second; } APValue &createTemporary(const void *Key, bool IsLifetimeExtended); }; @@ -347,7 +347,8 @@ namespace { PartialDiagnostic *Diag; public: - explicit OptionalDiagnostic(PartialDiagnostic *Diag = 0) : Diag(Diag) {} + explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr) + : Diag(Diag) {} template<typename T> OptionalDiagnostic &operator<<(const T &v) { @@ -474,13 +475,30 @@ namespace { /// Evaluate in any way we know how. Don't worry about side-effects that /// can't be modeled. - EM_IgnoreSideEffects + EM_IgnoreSideEffects, + + /// Evaluate as a constant expression. Stop if we find that the expression + /// is not a constant expression. Some expressions can be retried in the + /// optimizer if we don't constant fold them here, but in an unevaluated + /// context we try to fold them immediately since the optimizer never + /// gets a chance to look at it. + EM_ConstantExpressionUnevaluated, + + /// Evaluate as a potential constant expression. Keep going if we hit a + /// construct that we can't evaluate yet (because we don't yet know the + /// value of something) but stop if we hit something that could never be + /// a constant expression. Some expressions can be retried in the + /// optimizer if we don't constant fold them here, but in an unevaluated + /// context we try to fold them immediately since the optimizer never + /// gets a chance to look at it. + EM_PotentialConstantExpressionUnevaluated } EvalMode; /// Are we checking whether the expression is a potential constant /// expression? bool checkingPotentialConstantExpression() const { - return EvalMode == EM_PotentialConstantExpression; + return EvalMode == EM_PotentialConstantExpression || + EvalMode == EM_PotentialConstantExpressionUnevaluated; } /// Are we checking an expression for overflow? @@ -489,12 +507,13 @@ namespace { bool checkingForOverflow() { return EvalMode == EM_EvaluateForOverflow; } EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode) - : Ctx(const_cast<ASTContext&>(C)), EvalStatus(S), CurrentCall(0), + : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), CurrentCall(nullptr), CallStackDepth(0), NextCallIndex(1), StepsLeft(getLangOpts().ConstexprStepLimit), - BottomFrame(*this, SourceLocation(), 0, 0, 0), - EvaluatingDecl((const ValueDecl*)0), EvaluatingDeclValue(0), - HasActiveDiagnostic(false), EvalMode(Mode) {} + BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr), + EvaluatingDecl((const ValueDecl *)nullptr), + EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), + EvalMode(Mode) {} void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; @@ -527,7 +546,7 @@ namespace { CallStackFrame *Frame = CurrentCall; while (Frame->Index > CallIndex) Frame = Frame->Caller; - return (Frame->Index == CallIndex) ? Frame : 0; + return (Frame->Index == CallIndex) ? Frame : nullptr; } bool nextStep(const Stmt *S) { @@ -573,6 +592,8 @@ namespace { // some later problem. case EM_ConstantExpression: case EM_PotentialConstantExpression: + case EM_ConstantExpressionUnevaluated: + case EM_PotentialConstantExpressionUnevaluated: HasActiveDiagnostic = false; return OptionalDiagnostic(); } @@ -644,11 +665,13 @@ namespace { bool keepEvaluatingAfterSideEffect() { switch (EvalMode) { case EM_PotentialConstantExpression: + case EM_PotentialConstantExpressionUnevaluated: case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: return true; case EM_ConstantExpression: + case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: return false; } @@ -670,10 +693,12 @@ namespace { switch (EvalMode) { case EM_PotentialConstantExpression: + case EM_PotentialConstantExpressionUnevaluated: case EM_EvaluateForOverflow: return true; case EM_ConstantExpression: + case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_IgnoreSideEffects: return false; @@ -696,7 +721,9 @@ namespace { Info.EvalStatus.Diag->empty() && !Info.EvalStatus.HasSideEffects), OldMode(Info.EvalMode) { - if (Enabled && Info.EvalMode == EvalInfo::EM_ConstantExpression) + if (Enabled && + (Info.EvalMode == EvalInfo::EM_ConstantExpression || + Info.EvalMode == EvalInfo::EM_ConstantExpressionUnevaluated)) Info.EvalMode = EvalInfo::EM_ConstantFold; } void keepDiagnostics() { Enabled = false; } @@ -716,7 +743,7 @@ namespace { public: SpeculativeEvaluationRAII(EvalInfo &Info, - SmallVectorImpl<PartialDiagnosticAt> *NewDiag = 0) + SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr) : Info(Info), Old(Info.EvalStatus) { Info.EvalStatus.Diag = NewDiag; // If we're speculatively evaluating, we may have skipped over some @@ -943,7 +970,7 @@ namespace { // any object: we won't use such a designator for anything. if (!Info.getLangOpts().CPlusPlus11) Designator.setInvalid(); - return checkNullPointer(Info, E, CSK) && + return (CSK == CSK_ArrayToPointer || checkNullPointer(Info, E, CSK)) && Designator.checkSubobject(Info, E, CSK); } @@ -961,7 +988,7 @@ namespace { Designator.addComplexUnchecked(EltTy, Imag); } void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { - if (checkNullPointer(Info, E, CSK_ArrayIndex)) + if (N && checkNullPointer(Info, E, CSK_ArrayIndex)) Designator.adjustIndex(Info, E, N); } }; @@ -1141,7 +1168,7 @@ static int64_t getExtValue(const APSInt &Value) { /// Should this call expression be treated as a string literal? static bool IsStringLiteralCall(const CallExpr *E) { - unsigned Builtin = E->isBuiltinCall(); + unsigned Builtin = E->getBuiltinCallee(); return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString || Builtin == Builtin::BI__builtin___NSStringMakeConstantString); } @@ -1242,11 +1269,29 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, LVal.getLValueCallIndex() == 0) && "have call index for global lvalue"); - // Check if this is a thread-local variable. if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { if (const VarDecl *Var = dyn_cast<const VarDecl>(VD)) { + // Check if this is a thread-local variable. if (Var->getTLSKind()) return false; + + // A dllimport variable never acts like a constant. + if (Var->hasAttr<DLLImportAttr>()) + return false; + } + if (const auto *FD = dyn_cast<const FunctionDecl>(VD)) { + // __declspec(dllimport) must be handled very carefully: + // We must never initialize an expression with the thunk in C++. + // Doing otherwise would allow the same id-expression to yield + // different addresses for the same function in different translation + // units. However, this means that we must dynamically initialize the + // expression with the contents of the import address table at runtime. + // + // The C language has no notion of ODR; furthermore, it has no notion of + // dynamic initialization. This means that we are permitted to + // perform initialization with the address of the thunk. + if (Info.getLangOpts().CPlusPlus && FD->hasAttr<DLLImportAttr>()) + return false; } } @@ -1276,7 +1321,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, /// Check that this core constant expression is of literal type, and if not, /// produce an appropriate diagnostic. static bool CheckLiteralType(EvalInfo &Info, const Expr *E, - const LValue *This = 0) { + const LValue *This = nullptr) { if (!E->isRValue() || E->getType()->isLiteralType(Info.Ctx)) return true; @@ -1307,6 +1352,11 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, return false; } + // We allow _Atomic(T) to be initialized from anything that T can be + // initialized from. + if (const AtomicType *AT = Type->getAs<AtomicType>()) + Type = AT->getValueType(); + // Core issue 1454: For a literal constant expression of array or class type, // each subobject of its value shall have been initialized by a constant // expression. @@ -1338,8 +1388,7 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, return false; } } - for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - I != E; ++I) { + for (const auto *I : RD->fields()) { if (!CheckConstantExpression(Info, DiagLoc, I->getType(), Value.getStructField(I->getFieldIndex()))) return false; @@ -1738,7 +1787,7 @@ static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result, static bool HandleLValueDirectBase(EvalInfo &Info, const Expr *E, LValue &Obj, const CXXRecordDecl *Derived, const CXXRecordDecl *Base, - const ASTRecordLayout *RL = 0) { + const ASTRecordLayout *RL = nullptr) { if (!RL) { if (Derived->isInvalidDecl()) return false; RL = &Info.Ctx.getASTRecordLayout(Derived); @@ -1791,7 +1840,7 @@ static bool HandleLValueBasePath(EvalInfo &Info, const CastExpr *E, /// currently described by LVal. static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, const FieldDecl *FD, - const ASTRecordLayout *RL = 0) { + const ASTRecordLayout *RL = nullptr) { if (!RL) { if (FD->getParent()->isInvalidDecl()) return false; RL = &Info.Ctx.getASTRecordLayout(FD->getParent()); @@ -1807,9 +1856,8 @@ static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, static bool HandleLValueIndirectMember(EvalInfo &Info, const Expr *E, LValue &LVal, const IndirectFieldDecl *IFD) { - for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(), - CE = IFD->chain_end(); C != CE; ++C) - if (!HandleLValueMember(Info, E, LVal, cast<FieldDecl>(*C))) + for (const auto *C : IFD->chain()) + if (!HandleLValueMember(Info, E, LVal, cast<FieldDecl>(C))) return false; return true; } @@ -2047,7 +2095,7 @@ struct CompleteObject { /// The type of the complete object. QualType Type; - CompleteObject() : Value(0) {} + CompleteObject() : Value(nullptr) {} CompleteObject(APValue *Value, QualType Type) : Value(Value), Type(Type) { assert(Value && "missing value for complete object"); @@ -2075,7 +2123,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, APValue *O = Obj.Value; QualType ObjType = Obj.Type; - const FieldDecl *LastField = 0; + const FieldDecl *LastField = nullptr; // Walk the designator's path to find the subobject. for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) { @@ -2098,7 +2146,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, return true; } - LastField = 0; + LastField = nullptr; if (ObjType->isArrayType()) { // Next subobject is an array element. const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType); @@ -2381,7 +2429,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, return CompleteObject(); } - CallStackFrame *Frame = 0; + CallStackFrame *Frame = nullptr; if (LVal.CallIndex) { Frame = Info.getCallFrame(LVal.CallIndex); if (!Frame) { @@ -2406,7 +2454,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, } // Compute value storage location and type of base object. - APValue *BaseVal = 0; + APValue *BaseVal = nullptr; QualType BaseType = getType(LVal.Base); if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl*>()) { @@ -2776,7 +2824,7 @@ struct IncDecSubobjectHandler { // if we're post-incrementing a complex. if (Old) { *Old = Subobj; - Old = 0; + Old = nullptr; } switch (Subobj.getKind()) { @@ -2913,6 +2961,7 @@ static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, if (Object->getType()->isLiteralType(Info.Ctx)) return EvaluateTemporary(Object, This, Info); + Info.Diag(Object, diag::note_constexpr_nonliteral) << Object->getType(); return false; } @@ -2934,14 +2983,14 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, bool IncludeMember = true) { MemberPtr MemPtr; if (!EvaluateMemberPointer(RHS, MemPtr, Info)) - return 0; + return nullptr; // C++11 [expr.mptr.oper]p6: If the second operand is the null pointer to // member value, the behavior is undefined. if (!MemPtr.getDecl()) { // FIXME: Specific diagnostic. Info.Diag(RHS); - return 0; + return nullptr; } if (MemPtr.isDerivedMember()) { @@ -2951,7 +3000,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() > LV.Designator.Entries.size()) { Info.Diag(RHS); - return 0; + return nullptr; } unsigned PathLengthToMember = LV.Designator.Entries.size() - MemPtr.Path.size(); @@ -2961,14 +3010,14 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, const CXXRecordDecl *MPDecl = MemPtr.Path[I]; if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) { Info.Diag(RHS); - return 0; + return nullptr; } } // Truncate the lvalue to the appropriate derived class. if (!CastToDerivedClass(Info, RHS, LV, MemPtr.getContainingRecord(), PathLengthToMember)) - return 0; + return nullptr; } else if (!MemPtr.Path.empty()) { // Extend the LValue path with the member pointer's path. LV.Designator.Entries.reserve(LV.Designator.Entries.size() + @@ -2983,24 +3032,24 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, for (unsigned I = 1, N = MemPtr.Path.size(); I != N; ++I) { const CXXRecordDecl *Base = MemPtr.Path[N - I - 1]; if (!HandleLValueDirectBase(Info, RHS, LV, RD, Base)) - return 0; + return nullptr; RD = Base; } // Finally cast to the class containing the member. if (!HandleLValueDirectBase(Info, RHS, LV, RD, MemPtr.getContainingRecord())) - return 0; + return nullptr; } // Add the member. Note that we cannot build bound member functions here. if (IncludeMember) { if (const FieldDecl *FD = dyn_cast<FieldDecl>(MemPtr.getDecl())) { if (!HandleLValueMember(Info, RHS, LV, FD)) - return 0; + return nullptr; } else if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(MemPtr.getDecl())) { if (!HandleLValueIndirectMember(Info, RHS, LV, IFD)) - return 0; + return nullptr; } else { llvm_unreachable("can't construct reference to bound member function"); } @@ -3020,7 +3069,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, MemberPtr MemPtr; EvaluateMemberPointer(BO->getRHS(), MemPtr, Info); } - return 0; + return nullptr; } return HandleMemberPointerAccess(Info, BO->getLHS()->getType(), LV, @@ -3092,14 +3141,18 @@ static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { Result.set(VD, Info.CurrentCall->Index); APValue &Val = Info.CurrentCall->createTemporary(VD, true); - if (!VD->getInit()) { + const Expr *InitE = VD->getInit(); + if (!InitE) { Info.Diag(D->getLocStart(), diag::note_constexpr_uninitialized) << false << VD->getType(); Val = APValue(); return false; } - if (!EvaluateInPlace(Val, Info, Result, VD->getInit())) { + if (InitE->isValueDependent()) + return false; + + if (!EvaluateInPlace(Val, Info, Result, InitE)) { // Wipe out any partially-computed value, to allow tracking that this // evaluation failed. Val = APValue(); @@ -3120,12 +3173,13 @@ static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, } static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, - const Stmt *S, const SwitchCase *SC = 0); + const Stmt *S, + const SwitchCase *SC = nullptr); /// Evaluate the body of a loop, and translate the result as appropriate. static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info, const Stmt *Body, - const SwitchCase *Case = 0) { + const SwitchCase *Case = nullptr) { BlockScopeRAII Scope(Info); switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, Body, Case)) { case ESR_Break: @@ -3159,7 +3213,7 @@ static EvalStmtResult EvaluateSwitch(APValue &Result, EvalInfo &Info, // Find the switch case corresponding to the value of the condition. // FIXME: Cache this lookup. - const SwitchCase *Found = 0; + const SwitchCase *Found = nullptr; for (const SwitchCase *SC = SS->getSwitchCaseList(); SC; SC = SC->getNextSwitchCase()) { if (isa<DefaultStmt>(SC)) { @@ -3224,7 +3278,7 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: if (Case == S) - Case = 0; + Case = nullptr; break; case Stmt::IfStmtClass: { @@ -3291,13 +3345,12 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, case Stmt::DeclStmtClass: { const DeclStmt *DS = cast<DeclStmt>(S); - for (DeclStmt::const_decl_iterator DclIt = DS->decl_begin(), - DclEnd = DS->decl_end(); DclIt != DclEnd; ++DclIt) { + for (const auto *DclIt : DS->decls()) { // Each declaration initialization is its own full-expression. // FIXME: This isn't quite right; if we're performing aggregate // initialization, each braced subexpression is its own full-expression. FullExpressionRAII Scope(Info); - if (!EvaluateDecl(Info, *DclIt) && !Info.keepEvaluatingAfterFailure()) + if (!EvaluateDecl(Info, DclIt) && !Info.keepEvaluatingAfterFailure()) return ESR_Failed; } return ESR_Succeeded; @@ -3315,11 +3368,10 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, BlockScopeRAII Scope(Info); const CompoundStmt *CS = cast<CompoundStmt>(S); - for (CompoundStmt::const_body_iterator BI = CS->body_begin(), - BE = CS->body_end(); BI != BE; ++BI) { - EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI, Case); + for (const auto *BI : CS->body()) { + EvalStmtResult ESR = EvaluateStmt(Result, Info, BI, Case); if (ESR == ESR_Succeeded) - Case = 0; + Case = nullptr; else if (ESR != ESR_CaseNotFound) return ESR; } @@ -3368,7 +3420,7 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody(), Case); if (ESR != ESR_Continue) return ESR; - Case = 0; + Case = nullptr; FullExpressionRAII CondScope(Info); if (!EvaluateAsBooleanCondition(DS->getCond(), Continue, Info)) @@ -3593,7 +3645,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc, EvalStmtResult ESR = EvaluateStmt(Result, Info, Body); if (ESR == ESR_Succeeded) { - if (Callee->getResultType()->isVoidType()) + if (Callee->getReturnType()->isVoidType()) return true; Info.Diag(Callee->getLocEnd(), diag::note_constexpr_no_return); } @@ -3659,15 +3711,14 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, #ifndef NDEBUG CXXRecordDecl::base_class_const_iterator BaseIt = RD->bases_begin(); #endif - for (CXXConstructorDecl::init_const_iterator I = Definition->init_begin(), - E = Definition->init_end(); I != E; ++I) { + for (const auto *I : Definition->inits()) { LValue Subobject = This; APValue *Value = &Result; // Determine the subobject to initialize. - FieldDecl *FD = 0; - if ((*I)->isBaseInitializer()) { - QualType BaseType((*I)->getBaseClass(), 0); + FieldDecl *FD = nullptr; + if (I->isBaseInitializer()) { + QualType BaseType(I->getBaseClass(), 0); #ifndef NDEBUG // Non-virtual base classes are initialized in the order in the class // definition. We have already checked for virtual base classes. @@ -3676,12 +3727,12 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, "base class initializers not in expected order"); ++BaseIt; #endif - if (!HandleLValueDirectBase(Info, (*I)->getInit(), Subobject, RD, + if (!HandleLValueDirectBase(Info, I->getInit(), Subobject, RD, BaseType->getAsCXXRecordDecl(), &Layout)) return false; Value = &Result.getStructBase(BasesSeen++); - } else if ((FD = (*I)->getMember())) { - if (!HandleLValueMember(Info, (*I)->getInit(), Subobject, FD, &Layout)) + } else if ((FD = I->getMember())) { + if (!HandleLValueMember(Info, I->getInit(), Subobject, FD, &Layout)) return false; if (RD->isUnion()) { Result = APValue(FD); @@ -3689,13 +3740,11 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, } else { Value = &Result.getStructField(FD->getFieldIndex()); } - } else if (IndirectFieldDecl *IFD = (*I)->getIndirectMember()) { + } else if (IndirectFieldDecl *IFD = I->getIndirectMember()) { // Walk the indirect field decl's chain to find the object to initialize, // and make sure we've initialized every step along it. - for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(), - CE = IFD->chain_end(); - C != CE; ++C) { - FD = cast<FieldDecl>(*C); + for (auto *C : IFD->chain()) { + FD = cast<FieldDecl>(C); CXXRecordDecl *CD = cast<CXXRecordDecl>(FD->getParent()); // Switch the union field if it differs. This happens if we had // preceding zero-initialization, and we're now initializing a union @@ -3710,7 +3759,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, *Value = APValue(APValue::UninitStruct(), CD->getNumBases(), std::distance(CD->field_begin(), CD->field_end())); } - if (!HandleLValueMember(Info, (*I)->getInit(), Subobject, FD)) + if (!HandleLValueMember(Info, I->getInit(), Subobject, FD)) return false; if (CD->isUnion()) Value = &Value->getUnionValue(); @@ -3722,8 +3771,8 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, } FullExpressionRAII InitScope(Info); - if (!EvaluateInPlace(*Value, Info, Subobject, (*I)->getInit()) || - (FD && FD->isBitField() && !truncateBitfieldValue(Info, (*I)->getInit(), + if (!EvaluateInPlace(*Value, Info, Subobject, I->getInit()) || + (FD && FD->isBitField() && !truncateBitfieldValue(Info, I->getInit(), *Value, FD))) { // If we're checking for a potential constant expression, evaluate all // initializers even if some of them fail. @@ -3742,15 +3791,14 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, //===----------------------------------------------------------------------===// namespace { -// FIXME: RetTy is always bool. Remove it. -template <class Derived, typename RetTy=bool> +template <class Derived> class ExprEvaluatorBase - : public ConstStmtVisitor<Derived, RetTy> { + : public ConstStmtVisitor<Derived, bool> { private: - RetTy DerivedSuccess(const APValue &V, const Expr *E) { + bool DerivedSuccess(const APValue &V, const Expr *E) { return static_cast<Derived*>(this)->Success(V, E); } - RetTy DerivedZeroInitialization(const Expr *E) { + bool DerivedZeroInitialization(const Expr *E) { return static_cast<Derived*>(this)->ZeroInitialization(E); } @@ -3795,14 +3843,14 @@ private: protected: EvalInfo &Info; - typedef ConstStmtVisitor<Derived, RetTy> StmtVisitorTy; + typedef ConstStmtVisitor<Derived, bool> StmtVisitorTy; typedef ExprEvaluatorBase ExprEvaluatorBaseTy; OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { return Info.CCEDiag(E, D); } - RetTy ZeroInitialization(const Expr *E) { return Error(E); } + bool ZeroInitialization(const Expr *E) { return Error(E); } public: ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {} @@ -3819,28 +3867,28 @@ public: return Error(E, diag::note_invalid_subexpr_in_const_expr); } - RetTy VisitStmt(const Stmt *) { + bool VisitStmt(const Stmt *) { llvm_unreachable("Expression evaluator should not be called on stmts"); } - RetTy VisitExpr(const Expr *E) { + bool VisitExpr(const Expr *E) { return Error(E); } - RetTy VisitParenExpr(const ParenExpr *E) + bool VisitParenExpr(const ParenExpr *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } - RetTy VisitUnaryExtension(const UnaryOperator *E) + bool VisitUnaryExtension(const UnaryOperator *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } - RetTy VisitUnaryPlus(const UnaryOperator *E) + bool VisitUnaryPlus(const UnaryOperator *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } - RetTy VisitChooseExpr(const ChooseExpr *E) + bool VisitChooseExpr(const ChooseExpr *E) { return StmtVisitorTy::Visit(E->getChosenSubExpr()); } - RetTy VisitGenericSelectionExpr(const GenericSelectionExpr *E) + bool VisitGenericSelectionExpr(const GenericSelectionExpr *E) { return StmtVisitorTy::Visit(E->getResultExpr()); } - RetTy VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) + bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { return StmtVisitorTy::Visit(E->getReplacement()); } - RetTy VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) + bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { return StmtVisitorTy::Visit(E->getExpr()); } - RetTy VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { + bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { // The initializer may not have been parsed yet, or might be erroneous. if (!E->getExpr()) return Error(E); @@ -3848,19 +3896,19 @@ public: } // We cannot create any objects for which cleanups are required, so there is // nothing to do here; all cleanups must come from unevaluated subexpressions. - RetTy VisitExprWithCleanups(const ExprWithCleanups *E) + bool VisitExprWithCleanups(const ExprWithCleanups *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } - RetTy VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) { + bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) { CCEDiag(E, diag::note_constexpr_invalid_cast) << 0; return static_cast<Derived*>(this)->VisitCastExpr(E); } - RetTy VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) { + bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) { CCEDiag(E, diag::note_constexpr_invalid_cast) << 1; return static_cast<Derived*>(this)->VisitCastExpr(E); } - RetTy VisitBinaryOperator(const BinaryOperator *E) { + bool VisitBinaryOperator(const BinaryOperator *E) { switch (E->getOpcode()) { default: return Error(E); @@ -3882,7 +3930,7 @@ public: } } - RetTy VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) { + bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) { // Evaluate and cache the common expression. We treat it as a temporary, // even though it's not quite the same thing. if (!Evaluate(Info.CurrentCall->createTemporary(E->getOpaqueValue(), false), @@ -3892,7 +3940,7 @@ public: return HandleConditionalOperator(E); } - RetTy VisitConditionalOperator(const ConditionalOperator *E) { + bool VisitConditionalOperator(const ConditionalOperator *E) { bool IsBcpCall = false; // If the condition (ignoring parens) is a __builtin_constant_p call, // the result is a constant expression if it can be folded without @@ -3900,7 +3948,7 @@ public: // for discussion. if (const CallExpr *CallCE = dyn_cast<CallExpr>(E->getCond()->IgnoreParenCasts())) - if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p) + if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) IsBcpCall = true; // Always assume __builtin_constant_p(...) ? ... : ... is a potential @@ -3917,7 +3965,7 @@ public: return true; } - RetTy VisitOpaqueValueExpr(const OpaqueValueExpr *E) { + bool VisitOpaqueValueExpr(const OpaqueValueExpr *E) { if (APValue *Value = Info.CurrentCall->getTemporary(E)) return DerivedSuccess(*Value, E); @@ -3931,18 +3979,18 @@ public: return StmtVisitorTy::Visit(Source); } - RetTy VisitCallExpr(const CallExpr *E) { + bool VisitCallExpr(const CallExpr *E) { const Expr *Callee = E->getCallee()->IgnoreParens(); QualType CalleeType = Callee->getType(); - const FunctionDecl *FD = 0; - LValue *This = 0, ThisVal; + const FunctionDecl *FD = nullptr; + LValue *This = nullptr, ThisVal; ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; // Extract function decl and 'this' pointer from the callee. if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { - const ValueDecl *Member = 0; + const ValueDecl *Member = nullptr; if (const MemberExpr *ME = dyn_cast<MemberExpr>(Callee)) { // Explicit bound member calls, such as x.f() or p->g(); if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal)) @@ -4004,7 +4052,7 @@ public: isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isVirtual()) return Error(E, diag::note_constexpr_virtual_call); - const FunctionDecl *Definition = 0; + const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); APValue Result; @@ -4016,28 +4064,28 @@ public: return DerivedSuccess(Result, E); } - RetTy VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { + bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { return StmtVisitorTy::Visit(E->getInitializer()); } - RetTy VisitInitListExpr(const InitListExpr *E) { + bool VisitInitListExpr(const InitListExpr *E) { if (E->getNumInits() == 0) return DerivedZeroInitialization(E); if (E->getNumInits() == 1) return StmtVisitorTy::Visit(E->getInit(0)); return Error(E); } - RetTy VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { + bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { return DerivedZeroInitialization(E); } - RetTy VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { + bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { return DerivedZeroInitialization(E); } - RetTy VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { + bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { return DerivedZeroInitialization(E); } /// A member expression where the object is a prvalue is itself a prvalue. - RetTy VisitMemberExpr(const MemberExpr *E) { + bool VisitMemberExpr(const MemberExpr *E) { assert(!E->isArrow() && "missing call to bound member function?"); APValue Val; @@ -4061,7 +4109,7 @@ public: DerivedSuccess(Result, E); } - RetTy VisitCastExpr(const CastExpr *E) { + bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: break; @@ -4093,13 +4141,13 @@ public: return Error(E); } - RetTy VisitUnaryPostInc(const UnaryOperator *UO) { + bool VisitUnaryPostInc(const UnaryOperator *UO) { return VisitUnaryPostIncDec(UO); } - RetTy VisitUnaryPostDec(const UnaryOperator *UO) { + bool VisitUnaryPostDec(const UnaryOperator *UO) { return VisitUnaryPostIncDec(UO); } - RetTy VisitUnaryPostIncDec(const UnaryOperator *UO) { + bool VisitUnaryPostIncDec(const UnaryOperator *UO) { if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure()) return Error(UO); @@ -4113,7 +4161,7 @@ public: return DerivedSuccess(RVal, UO); } - RetTy VisitStmtExpr(const StmtExpr *E) { + bool VisitStmtExpr(const StmtExpr *E) { // We will have checked the full-expressions inside the statement expression // when they were completed, and don't need to check them again now. if (Info.checkingForOverflow()) @@ -4162,11 +4210,11 @@ public: namespace { template<class Derived> class LValueExprEvaluatorBase - : public ExprEvaluatorBase<Derived, bool> { + : public ExprEvaluatorBase<Derived> { protected: LValue &Result; typedef LValueExprEvaluatorBase LValueExprEvaluatorBaseTy; - typedef ExprEvaluatorBase<Derived, bool> ExprEvaluatorBaseTy; + typedef ExprEvaluatorBase<Derived> ExprEvaluatorBaseTy; bool Success(APValue::LValueBase B) { Result.set(B); @@ -4356,7 +4404,7 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { } bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { - CallStackFrame *Frame = 0; + CallStackFrame *Frame = nullptr; if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) Frame = Info.CurrentCall; @@ -4533,7 +4581,7 @@ bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) { return handleIncDec( this->Info, UO, Result, UO->getSubExpr()->getType(), - UO->isIncrementOp(), 0); + UO->isIncrementOp(), nullptr); } bool LValueExprEvaluator::VisitCompoundAssignOperator( @@ -4584,7 +4632,7 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { namespace { class PointerExprEvaluator - : public ExprEvaluatorBase<PointerExprEvaluator, bool> { + : public ExprEvaluatorBase<PointerExprEvaluator> { LValue &Result; bool Success(const Expr *E) { @@ -4601,7 +4649,7 @@ public: return true; } bool ZeroInitialization(const Expr *E) { - return Success((Expr*)0); + return Success((Expr*)nullptr); } bool VisitBinaryOperator(const BinaryOperator *E); @@ -4623,8 +4671,13 @@ public: // Can't look at 'this' when checking a potential constant expression. if (Info.checkingPotentialConstantExpression()) return false; - if (!Info.CurrentCall->This) - return Error(E); + if (!Info.CurrentCall->This) { + if (Info.getLangOpts().CPlusPlus11) + Info.Diag(E, diag::note_constexpr_this) << E->isImplicit(); + else + Info.Diag(E); + return false; + } Result = *Info.CurrentCall->This; return true; } @@ -4729,7 +4782,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { if (Value.isInt()) { unsigned Size = Info.Ctx.getTypeSize(E->getType()); uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue(); - Result.Base = (Expr*)0; + Result.Base = (Expr*)nullptr; Result.Offset = CharUnits::fromQuantity(N); Result.CallIndex = 0; Result.Designator.setInvalid(); @@ -4769,7 +4822,7 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (IsStringLiteralCall(E)) return Success(E); - switch (E->isBuiltinCall()) { + switch (E->getBuiltinCallee()) { case Builtin::BI__builtin_addressof: return EvaluateLValue(E->getArg(0), Result, Info); @@ -4784,7 +4837,7 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { namespace { class MemberPointerExprEvaluator - : public ExprEvaluatorBase<MemberPointerExprEvaluator, bool> { + : public ExprEvaluatorBase<MemberPointerExprEvaluator> { MemberPtr &Result; bool Success(const ValueDecl *D) { @@ -4801,7 +4854,7 @@ public: return true; } bool ZeroInitialization(const Expr *E) { - return Success((const ValueDecl*)0); + return Success((const ValueDecl*)nullptr); } bool VisitCastExpr(const CastExpr *E); @@ -4872,7 +4925,7 @@ bool MemberPointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { namespace { class RecordExprEvaluator - : public ExprEvaluatorBase<RecordExprEvaluator, bool> { + : public ExprEvaluatorBase<RecordExprEvaluator> { const LValue &This; APValue &Result; public: @@ -4925,14 +4978,13 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E, } } - for (RecordDecl::field_iterator I = RD->field_begin(), End = RD->field_end(); - I != End; ++I) { + for (const auto *I : RD->fields()) { // -- if T is a reference type, no initialization is performed. if (I->getType()->isReferenceType()) continue; LValue Subobject = This; - if (!HandleLValueMember(Info, E, Subobject, *I, &Layout)) + if (!HandleLValueMember(Info, E, Subobject, I, &Layout)) return false; ImplicitValueInitExpr VIE(I->getType()); @@ -4952,7 +5004,7 @@ bool RecordExprEvaluator::ZeroInitialization(const Expr *E) { // object's first non-static named data member is zero-initialized RecordDecl::field_iterator I = RD->field_begin(); if (I == RD->field_end()) { - Result = APValue((const FieldDecl*)0); + Result = APValue((const FieldDecl*)nullptr); return true; } @@ -5040,8 +5092,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { std::distance(RD->field_begin(), RD->field_end())); unsigned ElementNo = 0; bool Success = true; - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { + for (const auto *Field : RD->fields()) { // Anonymous bit-fields are not considered members of the class for // purposes of aggregate initialization. if (Field->isUnnamedBitfield()) @@ -5054,7 +5105,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { // FIXME: Diagnostics here should point to the end of the initializer // list, not the start. if (!HandleLValueMember(Info, HaveInit ? E->getInit(ElementNo) : E, - Subobject, *Field, &Layout)) + Subobject, Field, &Layout)) return false; // Perform an implicit value-initialization for members beyond the end of @@ -5069,7 +5120,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) || (Field->isBitField() && !truncateBitfieldValue(Info, Init, - FieldVal, *Field))) { + FieldVal, Field))) { if (!Info.keepEvaluatingAfterFailure()) return false; Success = false; @@ -5100,7 +5151,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { return ZeroInitialization(E); } - const FunctionDecl *Definition = 0; + const FunctionDecl *Definition = nullptr; FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) @@ -5234,7 +5285,7 @@ static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info) { namespace { class VectorExprEvaluator - : public ExprEvaluatorBase<VectorExprEvaluator, bool> { + : public ExprEvaluatorBase<VectorExprEvaluator> { APValue &Result; public: @@ -5415,7 +5466,7 @@ bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { namespace { class ArrayExprEvaluator - : public ExprEvaluatorBase<ArrayExprEvaluator, bool> { + : public ExprEvaluatorBase<ArrayExprEvaluator> { const LValue &This; APValue &Result; public: @@ -5487,7 +5538,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { unsigned NumEltsToInit = E->getNumInits(); unsigned NumElts = CAT->getSize().getZExtValue(); - const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : 0; + const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : nullptr; // If the initializer might depend on the array index, run it for each // array element. For now, just whitelist non-class value-initialization. @@ -5582,7 +5633,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, return EvaluateInPlace(*Value, Info, Subobject, &VIE); } - const FunctionDecl *Definition = 0; + const FunctionDecl *Definition = nullptr; FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) @@ -5610,7 +5661,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, namespace { class IntExprEvaluator - : public ExprEvaluatorBase<IntExprEvaluator, bool> { + : public ExprEvaluatorBase<IntExprEvaluator> { APValue &Result; public: IntExprEvaluator(EvalInfo &info, APValue &result) @@ -5716,14 +5767,6 @@ public: return ZeroInitialization(E); } - bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) { - return Success(E->getValue(), E); - } - - bool VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) { - return Success(E->getValue(), E); - } - bool VisitTypeTraitExpr(const TypeTraitExpr *E) { return Success(E->getValue(), E); } @@ -5964,7 +6007,7 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) { } bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { - switch (unsigned BuiltinOp = E->isBuiltinCall()) { + switch (unsigned BuiltinOp = E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); @@ -5983,7 +6026,17 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { // Expression had no side effects, but we couldn't statically determine the // size of the referenced object. - return Error(E); + switch (Info.EvalMode) { + case EvalInfo::EM_ConstantExpression: + case EvalInfo::EM_PotentialConstantExpression: + case EvalInfo::EM_ConstantFold: + case EvalInfo::EM_EvaluateForOverflow: + case EvalInfo::EM_IgnoreSideEffects: + return Error(E); + case EvalInfo::EM_ConstantExpressionUnevaluated: + case EvalInfo::EM_PotentialConstantExpressionUnevaluated: + return Success(-1ULL, E); + } } case Builtin::BI__builtin_bswap16: @@ -6005,7 +6058,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_clz: case Builtin::BI__builtin_clzl: - case Builtin::BI__builtin_clzll: { + case Builtin::BI__builtin_clzll: + case Builtin::BI__builtin_clzs: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; @@ -6020,7 +6074,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: - case Builtin::BI__builtin_ctzll: { + case Builtin::BI__builtin_ctzll: + case Builtin::BI__builtin_ctzs: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; @@ -6256,11 +6311,11 @@ class DataRecursiveIntBinOpEvaluator { const Expr *E; EvalResult LHSResult; // meaningful only for binary operator expression. enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind; - - Job() : StoredInfo(0) { } + + Job() : StoredInfo(nullptr) {} void startSpeculativeEval(EvalInfo &Info) { OldEvalStatus = Info.EvalStatus; - Info.EvalStatus.Diag = 0; + Info.EvalStatus.Diag = nullptr; StoredInfo = &Info; } ~Job() { @@ -6886,8 +6941,9 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { } CharUnits IntExprEvaluator::GetAlignOfType(QualType T) { - // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the - // result shall be the alignment of the referenced type." + // C++ [expr.alignof]p3: + // When alignof is applied to a reference type, the result is the + // alignment of the referenced type. if (const ReferenceType *Ref = T->getAs<ReferenceType>()) T = Ref->getPointeeType(); @@ -6906,7 +6962,7 @@ CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) { // alignof decl is always accepted, even if it doesn't make sense: we default // to 1 in those cases. if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) - return Info.Ctx.getDeclAlign(DRE->getDecl(), + return Info.Ctx.getDeclAlign(DRE->getDecl(), /*RefAsPointee*/true); if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) @@ -7109,6 +7165,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: case CK_NonAtomicToAtomic: + case CK_AddressSpaceConversion: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -7247,7 +7304,7 @@ bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { namespace { class FloatExprEvaluator - : public ExprEvaluatorBase<FloatExprEvaluator, bool> { + : public ExprEvaluatorBase<FloatExprEvaluator> { APFloat &Result; public: FloatExprEvaluator(EvalInfo &info, APFloat &result) @@ -7308,7 +7365,7 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, } bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { - switch (E->isBuiltinCall()) { + switch (E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); @@ -7463,7 +7520,7 @@ bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) { namespace { class ComplexExprEvaluator - : public ExprEvaluatorBase<ComplexExprEvaluator, bool> { + : public ExprEvaluatorBase<ComplexExprEvaluator> { ComplexValue &Result; public: @@ -7581,6 +7638,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: case CK_NonAtomicToAtomic: + case CK_AddressSpaceConversion: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -7847,7 +7905,7 @@ bool ComplexExprEvaluator::VisitInitListExpr(const InitListExpr *E) { namespace { class AtomicExprEvaluator : - public ExprEvaluatorBase<AtomicExprEvaluator, bool> { + public ExprEvaluatorBase<AtomicExprEvaluator> { APValue &Result; public: AtomicExprEvaluator(EvalInfo &Info, APValue &Result) @@ -7887,7 +7945,7 @@ static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info) { namespace { class VoidExprEvaluator - : public ExprEvaluatorBase<VoidExprEvaluator, bool> { + : public ExprEvaluatorBase<VoidExprEvaluator> { public: VoidExprEvaluator(EvalInfo &Info) : ExprEvaluatorBaseTy(Info) {} @@ -7902,6 +7960,16 @@ public: return true; } } + + bool VisitCallExpr(const CallExpr *E) { + switch (E->getBuiltinCallee()) { + default: + return ExprEvaluatorBaseTy::VisitCallExpr(E); + case Builtin::BI__assume: + // The argument is not evaluated! + return true; + } + } }; } // end anonymous namespace @@ -7989,6 +8057,8 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { /// an object can indirectly refer to subobjects which were initialized earlier. static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, const Expr *E, bool AllowNonLiteralTypes) { + assert(!E->isValueDependent()); + if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E, &This)) return false; @@ -8008,6 +8078,9 @@ static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, /// EvaluateAsRValue - Try to evaluate this expression, performing an implicit /// lvalue-to-rvalue cast if it is an lvalue. static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { + if (E->getType().isNull()) + return false; + if (!CheckLiteralType(Info, E)) return false; @@ -8035,6 +8108,13 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, IsConst = true; return true; } + + // This case should be rare, but we need to check it before we check on + // the type below. + if (Exp->getType().isNull()) { + IsConst = false; + return true; + } // FIXME: Evaluating values of large array and record types can cause // performance problems. Only do so in C++11 for now. @@ -8292,10 +8372,20 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::MaterializeTemporaryExprClass: case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: - case Expr::InitListExprClass: case Expr::LambdaExprClass: return ICEDiag(IK_NotICE, E->getLocStart()); + case Expr::InitListExprClass: { + // C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the + // form "T x = { a };" is equivalent to "T x = a;". + // Unless we're initializing a reference, T is a scalar as it is known to be + // of integral or enumeration type. + if (E->isRValue()) + if (cast<InitListExpr>(E)->getNumInits() == 1) + return CheckICE(cast<InitListExpr>(E)->getInit(0), Ctx); + return ICEDiag(IK_NotICE, E->getLocStart()); + } + case Expr::SizeOfPackExprClass: case Expr::GNUNullExprClass: // GCC considers the GNU __null value to be an integral constant expression. @@ -8314,8 +8404,6 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::ObjCBoolLiteralExprClass: case Expr::CXXBoolLiteralExprClass: case Expr::CXXScalarValueInitExprClass: - case Expr::UnaryTypeTraitExprClass: - case Expr::BinaryTypeTraitExprClass: case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: @@ -8327,7 +8415,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { // constant expressions, but they can never be ICEs because an ICE cannot // contain an operand of (pointer to) function type. const CallExpr *CE = cast<CallExpr>(E); - if (CE->isBuiltinCall()) + if (CE->getBuiltinCallee()) return CheckEvalInICE(E, Ctx); return ICEDiag(IK_NotICE, E->getLocStart()); } @@ -8544,7 +8632,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { // extension. See GCC PR38377 for discussion. if (const CallExpr *CallCE = dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts())) - if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p) + if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) return CheckEvalInICE(E, Ctx); ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); if (CondResult.Kind == IK_NotICE) @@ -8602,7 +8690,7 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, bool Expr::isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc) const { if (Ctx.getLangOpts().CPlusPlus11) - return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, 0, Loc); + return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc); ICEDiag D = CheckICE(this, Ctx); if (D.Kind != IK_ICE) { @@ -8654,6 +8742,28 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, return IsConstExpr; } +bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, + const FunctionDecl *Callee, + ArrayRef<const Expr*> Args) const { + Expr::EvalStatus Status; + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated); + + ArgVector ArgValues(Args.size()); + for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end(); + I != E; ++I) { + if (!Evaluate(ArgValues[I - Args.begin()], Info, *I)) + // If evaluation fails, throw away the argument entirely. + ArgValues[I - Args.begin()] = APValue(); + if (Info.EvalStatus.HasSideEffects) + return false; + } + + // Build fake call to Callee. + CallStackFrame Frame(Info, Callee->getLocation(), Callee, /*This*/nullptr, + ArgValues.data()); + return Evaluate(Value, Info, this) && !Info.EvalStatus.HasSideEffects; +} + bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, SmallVectorImpl< PartialDiagnosticAt> &Diags) { @@ -8670,7 +8780,7 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, EvalInfo::EM_PotentialConstantExpression); const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); - const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : 0; + const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr; // Fabricate an arbitrary expression on the stack and pretend that it // is a temporary being used as the 'this' pointer. @@ -8689,8 +8799,32 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, Info.setEvaluatingDecl(This.getLValueBase(), Scratch); HandleConstructorCall(Loc, This, Args, CD, Info, Scratch); } else - HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : 0, + HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr, Args, FD->getBody(), Info, Scratch); return Diags.empty(); } + +bool Expr::isPotentialConstantExprUnevaluated(Expr *E, + const FunctionDecl *FD, + SmallVectorImpl< + PartialDiagnosticAt> &Diags) { + Expr::EvalStatus Status; + Status.Diag = &Diags; + + EvalInfo Info(FD->getASTContext(), Status, + EvalInfo::EM_PotentialConstantExpressionUnevaluated); + + // Fabricate a call stack frame to give the arguments a plausible cover story. + ArrayRef<const Expr*> Args; + ArgVector ArgValues(0); + bool Success = EvaluateArgs(Args, ArgValues, Info); + (void)Success; + assert(Success && + "Failed to set up arguments for potential constant evaluation"); + CallStackFrame Frame(Info, SourceLocation(), FD, nullptr, ArgValues.data()); + + APValue ResultScratch; + Evaluate(ResultScratch, Info, E); + return Diags.empty(); +} diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp index 96ebe92..8894107 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp @@ -14,16 +14,44 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ExternalASTSource.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/DeclarationName.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; ExternalASTSource::~ExternalASTSource() { } +void ExternalASTSource::FindFileRegionDecls(FileID File, unsigned Offset, + unsigned Length, + SmallVectorImpl<Decl *> &Decls) {} + +void ExternalASTSource::CompleteRedeclChain(const Decl *D) {} + +void ExternalASTSource::CompleteType(TagDecl *Tag) {} + +void ExternalASTSource::CompleteType(ObjCInterfaceDecl *Class) {} + +void ExternalASTSource::ReadComments() {} + +void ExternalASTSource::StartedDeserializing() {} + +void ExternalASTSource::FinishedDeserializing() {} + +void ExternalASTSource::StartTranslationUnit(ASTConsumer *Consumer) {} + void ExternalASTSource::PrintStats() { } +bool ExternalASTSource::layoutRecordType( + const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets) { + return false; +} + Decl *ExternalASTSource::GetExternalDecl(uint32_t ID) { - return 0; + return nullptr; } Selector ExternalASTSource::GetExternalSelector(uint32_t ID) { @@ -35,12 +63,12 @@ uint32_t ExternalASTSource::GetNumExternalSelectors() { } Stmt *ExternalASTSource::GetExternalDeclStmt(uint64_t Offset) { - return 0; + return nullptr; } CXXBaseSpecifier * ExternalASTSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { - return 0; + return nullptr; } bool @@ -60,3 +88,21 @@ ExternalASTSource::FindExternalLexicalDecls(const DeclContext *DC, } void ExternalASTSource::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { } + +uint32_t ExternalASTSource::incrementGeneration(ASTContext &C) { + uint32_t OldGeneration = CurrentGeneration; + + // Make sure the generation of the topmost external source for the context is + // incremented. That might not be us. + auto *P = C.getExternalSource(); + if (P && P != this) + CurrentGeneration = P->incrementGeneration(C); + else { + // FIXME: Only bump the generation counter if the current generation number + // has been observed? + if (!++CurrentGeneration) + llvm::report_fatal_error("generation counter overflowed", false); + } + + return OldGeneration; +} diff --git a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp index 3d64310..eb3020c 100644 --- a/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp +++ b/contrib/llvm/tools/clang/lib/AST/InheritViz.cpp @@ -93,26 +93,25 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) { // Display the base classes. const CXXRecordDecl *Decl = static_cast<const CXXRecordDecl *>(Type->getAs<RecordType>()->getDecl()); - for (CXXRecordDecl::base_class_const_iterator Base = Decl->bases_begin(); - Base != Decl->bases_end(); ++Base) { - QualType CanonBaseType = Context.getCanonicalType(Base->getType()); + for (const auto &Base : Decl->bases()) { + QualType CanonBaseType = Context.getCanonicalType(Base.getType()); // If this is not virtual inheritance, bump the direct base // count for the type. - if (!Base->isVirtual()) + if (!Base.isVirtual()) ++DirectBaseCount[CanonBaseType]; // Write out the node (if we need to). - WriteNode(Base->getType(), Base->isVirtual()); + WriteNode(Base.getType(), Base.isVirtual()); // Write out the edge. Out << " "; WriteNodeReference(Type, FromVirtual); Out << " -> "; - WriteNodeReference(Base->getType(), Base->isVirtual()); + WriteNodeReference(Base.getType(), Base.isVirtual()); // Write out edge attributes to show the kind of inheritance. - if (Base->isVirtual()) { + if (Base.isVirtual()) { Out << " [ style=\"dashed\" ]"; } Out << ";"; @@ -140,7 +139,7 @@ void CXXRecordDecl::viewInheritance(ASTContext& Context) const { int FD; SmallString<128> Filename; - error_code EC = + std::error_code EC = sys::fs::createTemporaryFile(Self.getAsString(), "dot", FD, Filename); if (EC) { llvm::errs() << "Error: " << EC.message() << "\n"; diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index 5784660..b5f8c0f 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -33,12 +33,17 @@ namespace { /// literals within a particular context. class ItaniumNumberingContext : public MangleNumberingContext { llvm::DenseMap<IdentifierInfo*, unsigned> VarManglingNumbers; + llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers; public: /// Variable decls are numbered by identifier. - virtual unsigned getManglingNumber(const VarDecl *VD) { + unsigned getManglingNumber(const VarDecl *VD, unsigned) override { return ++VarManglingNumbers[VD->getIdentifier()]; } + + unsigned getManglingNumber(const TagDecl *TD, unsigned) override { + return ++TagManglingNumbers[TD->getIdentifier()]; + } }; class ItaniumCXXABI : public CXXABI { @@ -48,7 +53,7 @@ public: ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { } std::pair<uint64_t, unsigned> - getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const { + getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override { const TargetInfo &Target = Context.getTargetInfo(); TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0); uint64_t Width = Target.getTypeWidth(PtrDiff); @@ -58,13 +63,17 @@ public: return std::make_pair(Width, Align); } - CallingConv getDefaultMethodCallConv(bool isVariadic) const { + CallingConv getDefaultMethodCallConv(bool isVariadic) const override { + const llvm::Triple &T = Context.getTargetInfo().getTriple(); + if (!isVariadic && T.isWindowsGNUEnvironment() && + T.getArch() == llvm::Triple::x86) + return CC_X86ThisCall; return CC_C; } // We cheat and just check that the class has a vtable pointer, and that it's // only big enough to have a vtable pointer and nothing more (or less). - bool isNearlyEmpty(const CXXRecordDecl *RD) const { + bool isNearlyEmpty(const CXXRecordDecl *RD) const override { // Check that the class has a vtable pointer. if (!RD->isDynamicClass()) @@ -76,21 +85,12 @@ public: return Layout.getNonVirtualSize() == PointerSize; } - virtual MangleNumberingContext *createMangleNumberingContext() const { + MangleNumberingContext *createMangleNumberingContext() const override { return new ItaniumNumberingContext(); } }; - -class ARMCXXABI : public ItaniumCXXABI { -public: - ARMCXXABI(ASTContext &Ctx) : ItaniumCXXABI(Ctx) { } -}; } CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) { return new ItaniumCXXABI(Ctx); } - -CXXABI *clang::CreateARMCXXABI(ASTContext &Ctx) { - return new ARMCXXABI(Ctx); -} diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index 0621d7b..977d6fc 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -11,7 +11,7 @@ // which is used in GCC 3.2 and newer (and many compilers that are // ABI-compatible with GCC): // -// http://www.codesourcery.com/public/cxx-abi/abi.html +// http://mentorembedded.github.io/cxx-abi/abi.html#mangling // //===----------------------------------------------------------------------===// #include "clang/AST/Mangle.h" @@ -21,6 +21,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/TypeLoc.h" @@ -87,7 +88,7 @@ static const RecordDecl *GetLocalClassDecl(const Decl *D) { D = cast<Decl>(DC); DC = getEffectiveDeclContext(D); } - return 0; + return nullptr; } static const FunctionDecl *getStructor(const FunctionDecl *fn) { @@ -101,11 +102,18 @@ static const NamedDecl *getStructor(const NamedDecl *decl) { const FunctionDecl *fn = dyn_cast_or_null<FunctionDecl>(decl); return (fn ? getStructor(fn) : decl); } - + +static bool isLambda(const NamedDecl *ND) { + const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND); + if (!Record) + return false; + + return Record->isLambda(); +} + static const unsigned UnknownArity = ~0U; class ItaniumMangleContextImpl : public ItaniumMangleContext { - llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds; typedef std::pair<const DeclContext*, IdentifierInfo*> DiscriminatorKeyTy; llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator; llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier; @@ -115,52 +123,47 @@ public: DiagnosticsEngine &Diags) : ItaniumMangleContext(Context, Diags) {} - uint64_t getAnonymousStructId(const TagDecl *TD) { - std::pair<llvm::DenseMap<const TagDecl *, - uint64_t>::iterator, bool> Result = - AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size())); - return Result.first->second; - } - /// @name Mangler Entry Points /// @{ - bool shouldMangleCXXName(const NamedDecl *D); - void mangleCXXName(const NamedDecl *D, raw_ostream &); - void mangleThunk(const CXXMethodDecl *MD, - const ThunkInfo &Thunk, - raw_ostream &); + bool shouldMangleCXXName(const NamedDecl *D) override; + bool shouldMangleStringLiteral(const StringLiteral *) override { + return false; + } + void mangleCXXName(const NamedDecl *D, raw_ostream &) override; + void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, + raw_ostream &) override; void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, const ThisAdjustment &ThisAdjustment, - raw_ostream &); - void mangleReferenceTemporary(const VarDecl *D, - raw_ostream &); - void mangleCXXVTable(const CXXRecordDecl *RD, - raw_ostream &); - void mangleCXXVTT(const CXXRecordDecl *RD, - raw_ostream &); + raw_ostream &) override; + void mangleReferenceTemporary(const VarDecl *D, unsigned ManglingNumber, + raw_ostream &) override; + void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) override; + void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) override; void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, - const CXXRecordDecl *Type, - raw_ostream &); - void mangleCXXRTTI(QualType T, raw_ostream &); - void mangleCXXRTTIName(QualType T, raw_ostream &); - void mangleTypeName(QualType T, raw_ostream &); + const CXXRecordDecl *Type, raw_ostream &) override; + void mangleCXXRTTI(QualType T, raw_ostream &) override; + void mangleCXXRTTIName(QualType T, raw_ostream &) override; + void mangleTypeName(QualType T, raw_ostream &) override; void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - raw_ostream &); + raw_ostream &) override; void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - raw_ostream &); + raw_ostream &) override; + + void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) override; + void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override; + void mangleDynamicAtExitDestructor(const VarDecl *D, + raw_ostream &Out) override; + void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &) override; + void mangleItaniumThreadLocalWrapper(const VarDecl *D, + raw_ostream &) override; - void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &); - void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out); - void mangleDynamicAtExitDestructor(const VarDecl *D, raw_ostream &Out); - void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &); - void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &); + void mangleStringLiteral(const StringLiteral *, raw_ostream &) override; bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { // Lambda closure types are already numbered. - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND)) - if (RD->isLambda()) - return false; + if (isLambda(ND)) + return false; // Anonymous tags are already numbered. if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) { @@ -250,7 +253,7 @@ class CXXNameMangler { public: CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, - const NamedDecl *D = 0) + const NamedDecl *D = nullptr) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0), SeqID(0) { // These can't be mangled without a ctor type or dtor type. @@ -285,11 +288,13 @@ public: void mangleNumber(int64_t Number); void mangleFloat(const llvm::APFloat &F); void mangleFunctionEncoding(const FunctionDecl *FD); + void mangleSeqID(unsigned SeqID); void mangleName(const NamedDecl *ND); void mangleType(QualType T); void mangleNameOrStandardSubstitution(const NamedDecl *ND); private: + bool mangleSubstitution(const NamedDecl *ND); bool mangleSubstitution(QualType T); bool mangleSubstitution(TemplateName Template); @@ -454,6 +459,25 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { if (!Context.shouldMangleDeclName(FD)) return; + if (FD->hasAttr<EnableIfAttr>()) { + FunctionTypeDepthState Saved = FunctionTypeDepth.push(); + Out << "Ua9enable_ifI"; + // FIXME: specific_attr_iterator iterates in reverse order. Fix that and use + // it here. + for (AttrVec::const_reverse_iterator I = FD->getAttrs().rbegin(), + E = FD->getAttrs().rend(); + I != E; ++I) { + EnableIfAttr *EIA = dyn_cast<EnableIfAttr>(*I); + if (!EIA) + continue; + Out << 'X'; + mangleExpression(EIA->getCond()); + Out << 'E'; + } + Out << 'E'; + FunctionTypeDepth.pop(Saved); + } + // Whether the mangling of a function type includes the return type depends on // the context and the nature of the function. The rules for deciding whether // the return type is included are: @@ -535,15 +559,7 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { return Spec->getSpecializedTemplate(); } - return 0; -} - -static bool isLambda(const NamedDecl *ND) { - const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND); - if (!Record) - return false; - - return Record->isLambda(); + return nullptr; } void CXXNameMangler::mangleName(const NamedDecl *ND) { @@ -570,7 +586,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { if (DC->isTranslationUnit() || isStdNamespace(DC)) { // Check if we have a template. - const TemplateArgumentList *TemplateArgs = 0; + const TemplateArgumentList *TemplateArgs = nullptr; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleUnscopedTemplateName(TD); mangleTemplateArgs(*TemplateArgs); @@ -833,6 +849,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, switch (type->getTypeClass()) { case Type::Builtin: case Type::Complex: + case Type::Adjusted: case Type::Decayed: case Type::Pointer: case Type::BlockPointer: @@ -983,26 +1000,27 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, // Pretend we had a different nested name specifier. newQualifier = NestedNameSpecifier::Create(getASTContext(), - /*prefix*/ 0, + /*prefix*/ nullptr, /*template*/ false, type.getTypePtr()); } else if (NamespaceDecl *nspace = dyn_cast<NamespaceDecl>(firstQualifierLookup)) { newQualifier = NestedNameSpecifier::Create(getASTContext(), - /*prefix*/ 0, + /*prefix*/ nullptr, nspace); } else if (NamespaceAliasDecl *alias = dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) { newQualifier = NestedNameSpecifier::Create(getASTContext(), - /*prefix*/ 0, + /*prefix*/ nullptr, alias); } else { // No sensible mangling to do here. - newQualifier = 0; + newQualifier = nullptr; } if (newQualifier) - return mangleUnresolvedPrefix(newQualifier, /*lookup*/ 0, recursive); + return mangleUnresolvedPrefix(newQualifier, /*lookup*/ nullptr, + recursive); } else { Out << "sr"; @@ -1025,26 +1043,25 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, DeclarationName name, unsigned knownArity) { if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup); - mangleUnqualifiedName(0, name, knownArity); + mangleUnqualifiedName(nullptr, name, knownArity); } static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) { assert(RD->isAnonymousStructOrUnion() && "Expected anonymous struct or union!"); - for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - I != E; ++I) { + for (const auto *I : RD->fields()) { if (I->getIdentifier()) - return *I; + return I; if (const RecordType *RT = I->getType()->getAs<RecordType>()) if (const FieldDecl *NamedDataMember = FindFirstNamedDataMember(RT->getDecl())) return NamedDataMember; - } + } // We didn't find a named data member. - return 0; + return nullptr; } void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, @@ -1148,7 +1165,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } // Get a unique id for the anonymous struct. - uint64_t AnonStructId = Context.getAnonymousStructId(TD); + unsigned AnonStructId = Context.getAnonymousStructId(TD); // Mangle it as a source name in the form // [n] $_<id> @@ -1250,7 +1267,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, } // Check if we have a template. - const TemplateArgumentList *TemplateArgs = 0; + const TemplateArgumentList *TemplateArgs = nullptr; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD, NoFunction); mangleTemplateArgs(*TemplateArgs); @@ -1490,7 +1507,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { return; // Check if we have a template. - const TemplateArgumentList *TemplateArgs = 0; + const TemplateArgumentList *TemplateArgs = nullptr; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); @@ -1514,7 +1531,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { if (OverloadedTemplateStorage *Overloaded = Template.getAsOverloadedTemplate()) { - mangleUnqualifiedName(0, (*Overloaded->begin())->getDeclName(), + mangleUnqualifiedName(nullptr, (*Overloaded->begin())->getDeclName(), UnknownArity); return; } @@ -1556,8 +1573,8 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND, void CXXNameMangler::mangleType(TemplateName TN) { if (mangleSubstitution(TN)) return; - - TemplateDecl *TD = 0; + + TemplateDecl *TD = nullptr; switch (TN.getKind()) { case TemplateName::QualifiedTemplate: @@ -1584,7 +1601,7 @@ void CXXNameMangler::mangleType(TemplateName TN) { // <class-enum-type> ::= <name> // <name> ::= <nested-name> - mangleUnresolvedPrefix(Dependent->getQualifier(), 0); + mangleUnresolvedPrefix(Dependent->getQualifier(), nullptr); mangleSourceName(Dependent->getIdentifier()); break; } @@ -1919,7 +1936,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // ::= x # long long, __int64 // ::= y # unsigned long long, __int64 // ::= n # __int128 - // UNSUPPORTED: ::= o # unsigned __int128 + // ::= o # unsigned __int128 // ::= f # float // ::= d # double // ::= e # long double, __float80 @@ -2012,11 +2029,11 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, // <bare-function-type> ::= <signature type>+ if (MangleReturnType) { FunctionTypeDepth.enterResultType(); - mangleType(Proto->getResultType()); + mangleType(Proto->getReturnType()); FunctionTypeDepth.leaveResultType(); } - if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) { + if (Proto->getNumParams() == 0 && !Proto->isVariadic()) { // <builtin-type> ::= v # void Out << 'v'; @@ -2024,10 +2041,8 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, return; } - for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), - ArgEnd = Proto->arg_type_end(); - Arg != ArgEnd; ++Arg) - mangleType(Context.getASTContext().getSignatureParameterType(*Arg)); + for (const auto &Arg : Proto->param_types()) + mangleType(Context.getASTContext().getSignatureParameterType(Arg)); FunctionTypeDepth.pop(saved); @@ -2158,11 +2173,20 @@ void CXXNameMangler::mangleType(const ComplexType *T) { void CXXNameMangler::mangleNeonVectorType(const VectorType *T) { QualType EltType = T->getElementType(); assert(EltType->isBuiltinType() && "Neon vector element not a BuiltinType"); - const char *EltName = 0; + const char *EltName = nullptr; if (T->getVectorKind() == VectorType::NeonPolyVector) { switch (cast<BuiltinType>(EltType)->getKind()) { - case BuiltinType::SChar: EltName = "poly8_t"; break; - case BuiltinType::Short: EltName = "poly16_t"; break; + case BuiltinType::SChar: + case BuiltinType::UChar: + EltName = "poly8_t"; + break; + case BuiltinType::Short: + case BuiltinType::UShort: + EltName = "poly16_t"; + break; + case BuiltinType::ULongLong: + EltName = "poly64_t"; + break; default: llvm_unreachable("unexpected Neon polynomial vector element type"); } } else { @@ -2175,13 +2199,14 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) { case BuiltinType::UInt: EltName = "uint32_t"; break; case BuiltinType::LongLong: EltName = "int64_t"; break; case BuiltinType::ULongLong: EltName = "uint64_t"; break; + case BuiltinType::Double: EltName = "float64_t"; break; case BuiltinType::Float: EltName = "float32_t"; break; case BuiltinType::Half: EltName = "float16_t";break; default: llvm_unreachable("unexpected Neon vector element type"); } } - const char *BaseName = 0; + const char *BaseName = nullptr; unsigned BitSize = (T->getNumElements() * getASTContext().getTypeSize(EltType)); if (BitSize == 64) @@ -2202,6 +2227,7 @@ static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) { return "Int16"; case BuiltinType::Int: return "Int32"; + case BuiltinType::Long: case BuiltinType::LongLong: return "Int64"; case BuiltinType::UChar: @@ -2210,6 +2236,7 @@ static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) { return "Uint16"; case BuiltinType::UInt: return "Uint32"; + case BuiltinType::ULong: case BuiltinType::ULongLong: return "Uint64"; case BuiltinType::Half: @@ -2245,7 +2272,7 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) { case BuiltinType::UShort: EltName = "Poly16"; break; - case BuiltinType::ULongLong: + case BuiltinType::ULong: EltName = "Poly64"; break; default: @@ -2270,8 +2297,13 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) { void CXXNameMangler::mangleType(const VectorType *T) { if ((T->getVectorKind() == VectorType::NeonVector || T->getVectorKind() == VectorType::NeonPolyVector)) { - if (getASTContext().getTargetInfo().getTriple().getArch() == - llvm::Triple::aarch64) + llvm::Triple Target = getASTContext().getTargetInfo().getTriple(); + llvm::Triple::ArchType Arch = + getASTContext().getTargetInfo().getTriple().getArch(); + if ((Arch == llvm::Triple::aarch64 || + Arch == llvm::Triple::aarch64_be || + Arch == llvm::Triple::arm64_be || + Arch == llvm::Triple::arm64) && !Target.isOSDarwin()) mangleAArch64NeonVectorType(T); else mangleNeonVectorType(T); @@ -2311,9 +2343,8 @@ void CXXNameMangler::mangleType(const ObjCObjectType *T) { SmallString<64> QualStr; llvm::raw_svector_ostream QualOS(QualStr); QualOS << "objcproto"; - ObjCObjectType::qual_iterator i = T->qual_begin(), e = T->qual_end(); - for ( ; i != e; ++i) { - StringRef name = (*i)->getName(); + for (const auto *I : T->quals()) { + StringRef name = I->getName(); QualOS << name.size() << name; } QualOS.flush(); @@ -2352,10 +2383,37 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { } void CXXNameMangler::mangleType(const DependentNameType *T) { + // Proposal by cxx-abi-dev, 2014-03-26 + // <class-enum-type> ::= <name> # non-dependent or dependent type name or + // # dependent elaborated type specifier using + // # 'typename' + // ::= Ts <name> # dependent elaborated type specifier using + // # 'struct' or 'class' + // ::= Tu <name> # dependent elaborated type specifier using + // # 'union' + // ::= Te <name> # dependent elaborated type specifier using + // # 'enum' + switch (T->getKeyword()) { + case ETK_Typename: + break; + case ETK_Struct: + case ETK_Class: + case ETK_Interface: + Out << "Ts"; + break; + case ETK_Union: + Out << "Tu"; + break; + case ETK_Enum: + Out << "Te"; + break; + default: + llvm_unreachable("unexpected keyword for dependent type name"); + } // Typename types are always nested Out << 'N'; manglePrefix(T->getQualifier()); - mangleSourceName(T->getIdentifier()); + mangleSourceName(T->getIdentifier()); Out << 'E'; } @@ -2438,7 +2496,7 @@ void CXXNameMangler::mangleType(const AutoType *T) { } void CXXNameMangler::mangleType(const AtomicType *T) { - // <type> ::= U <source-name> <type> # vendor extended type qualifier + // <type> ::= U <source-name> <type> # vendor extended type qualifier // (Until there's a standardized mangling...) Out << "U7_Atomic"; mangleType(T->getValueType()); @@ -2581,8 +2639,6 @@ recurse: case Expr::ShuffleVectorExprClass: case Expr::ConvertVectorExprClass: case Expr::StmtExprClass: - case Expr::UnaryTypeTraitExprClass: - case Expr::BinaryTypeTraitExprClass: case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: @@ -2618,7 +2674,6 @@ recurse: llvm_unreachable("cannot mangle opaque value; mangling wrong thing?"); case Expr::InitListExprClass: { - // Proposal by Jason Merrill, 2012-01-03 Out << "il"; const InitListExpr *InitList = cast<InitListExpr>(E); for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i) @@ -2683,7 +2738,6 @@ recurse: Out << '_'; mangleType(New->getAllocatedType()); if (New->hasInitializer()) { - // Proposal by Jason Merrill, 2012-01-03 if (New->getInitializationStyle() == CXXNewExpr::ListInit) Out << "il"; else @@ -2714,15 +2768,15 @@ recurse: case Expr::MemberExprClass: { const MemberExpr *ME = cast<MemberExpr>(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), - ME->getQualifier(), 0, ME->getMemberDecl()->getDeclName(), - Arity); + ME->getQualifier(), nullptr, + ME->getMemberDecl()->getDeclName(), Arity); break; } case Expr::UnresolvedMemberExprClass: { const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), - ME->getQualifier(), 0, ME->getMemberName(), + ME->getQualifier(), nullptr, ME->getMemberName(), Arity); if (ME->hasExplicitTemplateArgs()) mangleTemplateArgs(ME->getExplicitTemplateArgs()); @@ -2742,7 +2796,7 @@ recurse: case Expr::UnresolvedLookupExprClass: { const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E); - mangleUnresolvedName(ULE->getQualifier(), 0, ULE->getName(), Arity); + mangleUnresolvedName(ULE->getQualifier(), nullptr, ULE->getName(), Arity); // All the <unresolved-name> productions end in a // base-unresolved-name, where <template-args> are just tacked @@ -2769,7 +2823,6 @@ recurse: const CXXConstructExpr *CE = cast<CXXConstructExpr>(E); unsigned N = CE->getNumArgs(); - // Proposal by Jason Merrill, 2012-01-03 if (CE->isListInitialization()) Out << "tl"; else @@ -3005,7 +3058,8 @@ recurse: case Expr::DependentScopeDeclRefExprClass: { const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E); - mangleUnresolvedName(DRE->getQualifier(), 0, DRE->getDeclName(), Arity); + mangleUnresolvedName(DRE->getQualifier(), nullptr, DRE->getDeclName(), + Arity); // All the <unresolved-name> productions end in a // base-unresolved-name, where <template-args> are just tacked @@ -3342,10 +3396,8 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) { case TemplateArgument::Pack: { // <template-arg> ::= J <template-arg>* E Out << 'J'; - for (TemplateArgument::pack_iterator PA = A.pack_begin(), - PAEnd = A.pack_end(); - PA != PAEnd; ++PA) - mangleTemplateArg(*PA); + for (const auto &P : A.pack_elements()) + mangleTemplateArg(P); Out << 'E'; } } @@ -3360,6 +3412,27 @@ void CXXNameMangler::mangleTemplateParameter(unsigned Index) { Out << 'T' << (Index - 1) << '_'; } +void CXXNameMangler::mangleSeqID(unsigned SeqID) { + if (SeqID == 1) + Out << '0'; + else if (SeqID > 1) { + SeqID--; + + // <seq-id> is encoded in base-36, using digits and upper case letters. + char Buffer[7]; // log(2**32) / log(36) ~= 7 + MutableArrayRef<char> BufferRef(Buffer); + MutableArrayRef<char>::reverse_iterator I = BufferRef.rbegin(); + + for (; SeqID != 0; SeqID /= 36) { + unsigned C = SeqID % 36; + *I++ = (C < 10 ? '0' + C : 'A' + C - 10); + } + + Out.write(I.base(), I - BufferRef.rbegin()); + } + Out << '_'; +} + void CXXNameMangler::mangleExistingSubstitution(QualType type) { bool result = mangleSubstitution(type); assert(result && "no existing substitution for type"); @@ -3416,30 +3489,8 @@ bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) { return false; unsigned SeqID = I->second; - if (SeqID == 0) - Out << "S_"; - else { - SeqID--; - - // <seq-id> is encoded in base-36, using digits and upper case letters. - char Buffer[10]; - char *BufferPtr = llvm::array_endof(Buffer); - - if (SeqID == 0) *--BufferPtr = '0'; - - while (SeqID) { - assert(BufferPtr > Buffer && "Buffer overflow!"); - - char c = static_cast<char>(SeqID % 36); - - *--BufferPtr = (c < 10 ? '0' + c : 'A' + c - 10); - SeqID /= 36; - } - - Out << 'S' - << StringRef(BufferPtr, llvm::array_endof(Buffer)-BufferPtr) - << '_'; - } + Out << 'S'; + mangleSeqID(SeqID); return true; } @@ -3732,12 +3783,15 @@ ItaniumMangleContextImpl::mangleItaniumThreadLocalWrapper(const VarDecl *D, } void ItaniumMangleContextImpl::mangleReferenceTemporary(const VarDecl *D, + unsigned ManglingNumber, raw_ostream &Out) { // We match the GCC mangling here. // <special-name> ::= GR <object name> CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZGR"; Mangler.mangleName(D); + assert(ManglingNumber > 0 && "Reference temporary mangling number is zero!"); + Mangler.mangleSeqID(ManglingNumber - 1); } void ItaniumMangleContextImpl::mangleCXXVTable(const CXXRecordDecl *RD, @@ -3789,6 +3843,10 @@ void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) { mangleCXXRTTIName(Ty, Out); } +void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) { + llvm_unreachable("Can't mangle string literals"); +} + ItaniumMangleContext * ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) { return new ItaniumMangleContextImpl(Context, Diags); diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp index 231ef03..fdc00e3 100644 --- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp @@ -11,13 +11,13 @@ // //===----------------------------------------------------------------------===// #include "clang/AST/Attr.h" -#include "clang/AST/Mangle.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/Mangle.h" #include "clang/Basic/ABI.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -64,7 +64,7 @@ static bool isExternC(const NamedDecl *ND) { static StdOrFastCC getStdOrFastCallMangling(const ASTContext &Context, const NamedDecl *ND) { const TargetInfo &TI = Context.getTargetInfo(); - llvm::Triple Triple = TI.getTriple(); + const llvm::Triple &Triple = TI.getTriple(); if (!Triple.isOSWindows() || Triple.getArch() != llvm::Triple::x86) return SOF_OTHER; @@ -163,13 +163,9 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) { if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) if (!MD->isStatic()) ++ArgWords; - for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), - ArgEnd = Proto->arg_type_end(); - Arg != ArgEnd; ++Arg) { - QualType AT = *Arg; + for (const auto &AT : Proto->param_types()) // Size should be aligned to DWORD boundary ArgWords += llvm::RoundUpToAlignment(ASTContext.getTypeSize(AT), 32) / 32; - } Out << 4 * ArgWords; } @@ -246,7 +242,9 @@ void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName(); if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) OS << '(' << *CID << ')'; - OS << ' ' << MD->getSelector().getAsString() << ']'; + OS << ' '; + MD->getSelector().print(OS); + OS << ']'; Out << OS.str().size() << OS.str(); } diff --git a/contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp b/contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp index 91ef0e2..5f40f03 100644 --- a/contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MangleNumberingContext.cpp @@ -24,7 +24,7 @@ MangleNumberingContext::getManglingNumber(const CXXMethodDecl *CallOperator) { = CallOperator->getType()->getAs<FunctionProtoType>(); ASTContext &Context = CallOperator->getASTContext(); - QualType Key = Context.getFunctionType(Context.VoidTy, Proto->getArgTypes(), + QualType Key = Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), FunctionProtoType::ExtProtoInfo()); Key = Context.getCanonicalType(Key); return ++ManglingNumbers[Key->castAs<FunctionProtoType>()]; @@ -33,11 +33,13 @@ MangleNumberingContext::getManglingNumber(const CXXMethodDecl *CallOperator) { unsigned MangleNumberingContext::getManglingNumber(const BlockDecl *BD) { // FIXME: Compute a BlockPointerType? Not obvious how. - const Type *Ty = 0; + const Type *Ty = nullptr; return ++ManglingNumbers[Ty]; } unsigned -MangleNumberingContext::getManglingNumber(const TagDecl *TD) { - return ++TagManglingNumbers[TD->getIdentifier()]; +MangleNumberingContext::getStaticLocalNumber(const VarDecl *VD) { + // FIXME: Compute a BlockPointerType? Not obvious how. + const Type *Ty = nullptr; + return ++ManglingNumbers[Ty]; } diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp index 4a93ea1..6870315 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// #include "CXXABI.h" -#include "clang/AST/Attr.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/MangleNumberingContext.h" #include "clang/AST/RecordLayout.h" @@ -28,15 +28,15 @@ namespace { /// \brief Numbers things which need to correspond across multiple TUs. /// Typically these are things like static locals, lambdas, or blocks. class MicrosoftNumberingContext : public MangleNumberingContext { - unsigned NumStaticLocals; - public: - MicrosoftNumberingContext() : NumStaticLocals(0) { } + unsigned getManglingNumber(const VarDecl *VD, + unsigned MSLocalManglingNumber) override { + return MSLocalManglingNumber; + } - /// Static locals are numbered by source order. - virtual unsigned getManglingNumber(const VarDecl *VD) { - assert(VD->isStaticLocal()); - return ++NumStaticLocals; + unsigned getManglingNumber(const TagDecl *TD, + unsigned MSLocalManglingNumber) override { + return MSLocalManglingNumber; } }; @@ -46,16 +46,16 @@ public: MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } std::pair<uint64_t, unsigned> - getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const; + getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override; - CallingConv getDefaultMethodCallConv(bool isVariadic) const { + CallingConv getDefaultMethodCallConv(bool isVariadic) const override { if (!isVariadic && Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) return CC_X86ThisCall; return CC_C; } - bool isNearlyEmpty(const CXXRecordDecl *RD) const { + bool isNearlyEmpty(const CXXRecordDecl *RD) const override { // FIXME: Audit the corners if (!RD->isDynamicClass()) return false; @@ -69,7 +69,7 @@ public: Layout.getNonVirtualSize() == PointerSize * 2; } - MangleNumberingContext *createMangleNumberingContext() const { + MangleNumberingContext *createMangleNumberingContext() const override { return new MicrosoftNumberingContext(); } }; @@ -92,26 +92,27 @@ static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) { return false; } -static MSInheritanceModel MSInheritanceAttrToModel(attr::Kind Kind) { - switch (Kind) { - default: llvm_unreachable("expected MS inheritance attribute"); - case attr::SingleInheritance: return MSIM_Single; - case attr::MultipleInheritance: return MSIM_Multiple; - case attr::VirtualInheritance: return MSIM_Virtual; - case attr::UnspecifiedInheritance: return MSIM_Unspecified; - } +MSInheritanceAttr::Spelling CXXRecordDecl::calculateInheritanceModel() const { + if (!hasDefinition() || isParsingBaseSpecifiers()) + return MSInheritanceAttr::Keyword_unspecified_inheritance; + if (getNumVBases() > 0) + return MSInheritanceAttr::Keyword_virtual_inheritance; + if (usesMultipleInheritanceModel(this)) + return MSInheritanceAttr::Keyword_multiple_inheritance; + return MSInheritanceAttr::Keyword_single_inheritance; } -MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const { - if (Attr *IA = this->getAttr<MSInheritanceAttr>()) - return MSInheritanceAttrToModel(IA->getKind()); - // If there was no explicit attribute, the record must be defined already, and - // we can figure out the inheritance model from its other properties. - if (this->getNumVBases() > 0) - return MSIM_Virtual; - if (usesMultipleInheritanceModel(this)) - return this->isPolymorphic() ? MSIM_MultiplePolymorphic : MSIM_Multiple; - return this->isPolymorphic() ? MSIM_SinglePolymorphic : MSIM_Single; +MSInheritanceAttr::Spelling +CXXRecordDecl::getMSInheritanceModel() const { + MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>(); + assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!"); + return IA->getSemanticSpelling(); +} + +MSVtorDispAttr::Mode CXXRecordDecl::getMSVtorDispMode() const { + if (MSVtorDispAttr *VDA = getAttr<MSVtorDispAttr>()) + return VDA->getVtorDispMode(); + return MSVtorDispAttr::Mode(getASTContext().getLangOpts().VtorDispMode); } // Returns the number of pointer and integer slots used to represent a member @@ -133,49 +134,32 @@ MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const { // // offset. // int NonVirtualBaseAdjustment; // +// // The offset of the vb-table pointer within the object. Only needed for +// // incomplete types. +// int VBPtrOffset; +// // // An offset within the vb-table that selects the virtual base containing // // the member. Loading from this offset produces a new offset that is // // added to the address of the vb-table pointer to produce the base. // int VirtualBaseAdjustmentOffset; -// -// // The offset of the vb-table pointer within the object. Only needed for -// // incomplete types. -// int VBPtrOffset; // }; static std::pair<unsigned, unsigned> getMSMemberPointerSlots(const MemberPointerType *MPT) { - const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); - MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); - unsigned Ptrs; + const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); + MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); + unsigned Ptrs = 0; unsigned Ints = 0; - if (MPT->isMemberFunctionPointer()) { - // Member function pointers are a struct of a function pointer followed by a - // variable number of ints depending on the inheritance model used. The - // function pointer is a real function if it is non-virtual and a vftable - // slot thunk if it is virtual. The ints select the object base passed for - // the 'this' pointer. - Ptrs = 1; // First slot is always a function pointer. - switch (Inheritance) { - case MSIM_Unspecified: ++Ints; // VBTableOffset - case MSIM_Virtual: ++Ints; // VirtualBaseAdjustmentOffset - case MSIM_MultiplePolymorphic: - case MSIM_Multiple: ++Ints; // NonVirtualBaseAdjustment - case MSIM_SinglePolymorphic: - case MSIM_Single: break; // Nothing - } - } else { - // Data pointers are an aggregate of ints. The first int is an offset - // followed by vbtable-related offsets. - Ptrs = 0; - switch (Inheritance) { - case MSIM_Unspecified: ++Ints; // VBTableOffset - case MSIM_Virtual: ++Ints; // VirtualBaseAdjustmentOffset - case MSIM_MultiplePolymorphic: - case MSIM_Multiple: // Nothing - case MSIM_SinglePolymorphic: - case MSIM_Single: ++Ints; // Field offset - } - } + if (MPT->isMemberFunctionPointer()) + Ptrs = 1; + else + Ints = 1; + if (MSInheritanceAttr::hasNVOffsetField(MPT->isMemberFunctionPointer(), + Inheritance)) + Ints++; + if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) + Ints++; + if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance)) + Ints++; return std::make_pair(Ptrs, Ints); } @@ -185,14 +169,26 @@ std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign( assert(Target.getTriple().getArch() == llvm::Triple::x86 || Target.getTriple().getArch() == llvm::Triple::x86_64); unsigned Ptrs, Ints; - llvm::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT); + std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT); // The nominal struct is laid out with pointers followed by ints and aligned // to a pointer width if any are present and an int width otherwise. unsigned PtrSize = Target.getPointerWidth(0); unsigned IntSize = Target.getIntWidth(); uint64_t Width = Ptrs * PtrSize + Ints * IntSize; - unsigned Align = Ptrs > 0 ? Target.getPointerAlign(0) : Target.getIntAlign(); - Width = llvm::RoundUpToAlignment(Width, Align); + unsigned Align; + + // When MSVC does x86_32 record layout, it aligns aggregate member pointers to + // 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for + // function memptrs. + if (Ptrs + Ints > 1 && Target.getTriple().getArch() == llvm::Triple::x86) + Align = 8 * 8; + else if (Ptrs) + Align = Target.getPointerAlign(0); + else + Align = Target.getIntAlign(); + + if (Target.getTriple().getArch() == llvm::Triple::x86_64) + Width = llvm::RoundUpToAlignment(Width, Align); return std::make_pair(Width, Align); } diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 5256501..e6a6d09 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -14,17 +14,21 @@ #include "clang/AST/Mangle.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" -#include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/VTableBuilder.h" #include "clang/Basic/ABI.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/MathExtras.h" using namespace clang; @@ -71,10 +75,114 @@ static const FunctionDecl *getStructor(const FunctionDecl *fn) { return fn; } +static bool isLambda(const NamedDecl *ND) { + const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND); + if (!Record) + return false; + + return Record->isLambda(); +} + +/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the +/// Microsoft Visual C++ ABI. +class MicrosoftMangleContextImpl : public MicrosoftMangleContext { + typedef std::pair<const DeclContext *, IdentifierInfo *> DiscriminatorKeyTy; + llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator; + llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier; + llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds; + +public: + MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) + : MicrosoftMangleContext(Context, Diags) {} + bool shouldMangleCXXName(const NamedDecl *D) override; + bool shouldMangleStringLiteral(const StringLiteral *SL) override; + void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override; + void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, + raw_ostream &) override; + void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, + raw_ostream &) override; + void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, + const ThisAdjustment &ThisAdjustment, + raw_ostream &) override; + void mangleCXXVFTable(const CXXRecordDecl *Derived, + ArrayRef<const CXXRecordDecl *> BasePath, + raw_ostream &Out) override; + void mangleCXXVBTable(const CXXRecordDecl *Derived, + ArrayRef<const CXXRecordDecl *> BasePath, + raw_ostream &Out) override; + void mangleCXXRTTI(QualType T, raw_ostream &Out) override; + void mangleCXXRTTIName(QualType T, raw_ostream &Out) override; + void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived, + uint32_t NVOffset, int32_t VBPtrOffset, + uint32_t VBTableOffset, uint32_t Flags, + raw_ostream &Out) override; + void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived, + raw_ostream &Out) override; + void mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived, + raw_ostream &Out) override; + void + mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived, + ArrayRef<const CXXRecordDecl *> BasePath, + raw_ostream &Out) override; + void mangleTypeName(QualType T, raw_ostream &) override; + void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, + raw_ostream &) override; + void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, + raw_ostream &) override; + void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber, + raw_ostream &) override; + void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override; + void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override; + void mangleDynamicAtExitDestructor(const VarDecl *D, + raw_ostream &Out) override; + void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override; + bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { + // Lambda closure types are already numbered. + if (isLambda(ND)) + return false; + + const DeclContext *DC = getEffectiveDeclContext(ND); + if (!DC->isFunctionOrMethod()) + return false; + + // Use the canonical number for externally visible decls. + if (ND->isExternallyVisible()) { + disc = getASTContext().getManglingNumber(ND); + return true; + } + + // Anonymous tags are already numbered. + if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) { + if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl()) + return false; + } + + // Make up a reasonable number for internal decls. + unsigned &discriminator = Uniquifier[ND]; + if (!discriminator) + discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())]; + disc = discriminator; + return true; + } + + unsigned getLambdaId(const CXXRecordDecl *RD) { + assert(RD->isLambda() && "RD must be a lambda!"); + assert(!RD->isExternallyVisible() && "RD must not be visible!"); + assert(RD->getLambdaManglingNumber() == 0 && + "RD must not have a mangling number!"); + std::pair<llvm::DenseMap<const CXXRecordDecl *, unsigned>::iterator, bool> + Result = LambdaIds.insert(std::make_pair(RD, LambdaIds.size())); + return Result.first->second; + } + +private: + void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode); +}; + /// MicrosoftCXXNameMangler - Manage the mangling of a single name for the /// Microsoft Visual C++ ABI. class MicrosoftCXXNameMangler { - MangleContext &Context; + MicrosoftMangleContextImpl &Context; raw_ostream &Out; /// The "structor" is the top-level declaration being mangled, if @@ -85,9 +193,8 @@ class MicrosoftCXXNameMangler { typedef llvm::StringMap<unsigned> BackRefMap; BackRefMap NameBackReferences; - bool UseNameBackReferences; - typedef llvm::DenseMap<void*, unsigned> ArgBackRefMap; + typedef llvm::DenseMap<void *, unsigned> ArgBackRefMap; ArgBackRefMap TypeBackReferences; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -99,37 +206,38 @@ class MicrosoftCXXNameMangler { public: enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result }; - MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_) - : Context(C), Out(Out_), - Structor(0), StructorType(-1), - UseNameBackReferences(true), - PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == - 64) { } + MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_) + : Context(C), Out(Out_), Structor(nullptr), StructorType(-1), + PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == + 64) {} - MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_, + MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) - : Context(C), Out(Out_), - Structor(getStructor(D)), StructorType(Type), - UseNameBackReferences(true), - PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == - 64) { } + : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), + PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == + 64) {} raw_ostream &getStream() const { return Out; } void mangle(const NamedDecl *D, StringRef Prefix = "\01?"); void mangleName(const NamedDecl *ND); - void mangleDeclaration(const NamedDecl *ND); void mangleFunctionEncoding(const FunctionDecl *FD); void mangleVariableEncoding(const VarDecl *VD); + void mangleMemberDataPointer(const CXXRecordDecl *RD, const ValueDecl *VD); + void mangleMemberFunctionPointer(const CXXRecordDecl *RD, + const CXXMethodDecl *MD); + void mangleVirtualMemPtrThunk( + const CXXMethodDecl *MD, + const MicrosoftVTableContext::MethodVFTableLocation &ML); void mangleNumber(int64_t Number); void mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM = QMM_Mangle); - void mangleFunctionType(const FunctionType *T, const FunctionDecl *D = 0, + void mangleFunctionType(const FunctionType *T, + const FunctionDecl *D = nullptr, bool ForceInstMethod = false); - void manglePostfix(const DeclContext *DC, bool NoFunction = false); + void mangleNestedName(const NamedDecl *ND); private: - void disableBackReferences() { UseNameBackReferences = false; } void mangleUnqualifiedName(const NamedDecl *ND) { mangleUnqualifiedName(ND, ND->getDeclName()); } @@ -138,13 +246,15 @@ private: void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc); void mangleCXXDtorType(CXXDtorType T); void mangleQualifiers(Qualifiers Quals, bool IsMember); - void manglePointerQualifiers(Qualifiers Quals); + void mangleRefQualifier(RefQualifierKind RefQualifier); + void manglePointerCVQualifiers(Qualifiers Quals); + void manglePointerExtQualifiers(Qualifiers Quals, const Type *PointeeType); void mangleUnscopedTemplateName(const TemplateDecl *ND); - void mangleTemplateInstantiationName(const TemplateDecl *TD, - const TemplateArgumentList &TemplateArgs); + void + mangleTemplateInstantiationName(const TemplateDecl *TD, + const TemplateArgumentList &TemplateArgs); void mangleObjCMethodName(const ObjCMethodDecl *MD); - void mangleLocalName(const FunctionDecl *FD); void mangleArgumentType(QualType T, SourceRange Range); @@ -157,7 +267,7 @@ private: #undef ABSTRACT_TYPE #undef NON_CANONICAL_TYPE #undef TYPE - + void mangleType(const TagDecl *TD); void mangleDecayedArrayType(const ArrayType *T); void mangleArrayType(const ArrayType *T); @@ -171,47 +281,6 @@ private: const TemplateArgumentList &TemplateArgs); void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA); }; - -/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the -/// Microsoft Visual C++ ABI. -class MicrosoftMangleContextImpl : public MicrosoftMangleContext { -public: - MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) - : MicrosoftMangleContext(Context, Diags) {} - virtual bool shouldMangleCXXName(const NamedDecl *D); - virtual void mangleCXXName(const NamedDecl *D, raw_ostream &Out); - virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, - uint64_t OffsetInVFTable, - raw_ostream &); - virtual void mangleThunk(const CXXMethodDecl *MD, - const ThunkInfo &Thunk, - raw_ostream &); - virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, - const ThisAdjustment &ThisAdjustment, - raw_ostream &); - virtual void mangleCXXVFTable(const CXXRecordDecl *Derived, - ArrayRef<const CXXRecordDecl *> BasePath, - raw_ostream &Out); - virtual void mangleCXXVBTable(const CXXRecordDecl *Derived, - ArrayRef<const CXXRecordDecl *> BasePath, - raw_ostream &Out); - virtual void mangleCXXRTTI(QualType T, raw_ostream &); - virtual void mangleCXXRTTIName(QualType T, raw_ostream &); - virtual void mangleTypeName(QualType T, raw_ostream &); - virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - raw_ostream &); - virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - raw_ostream &); - virtual void mangleReferenceTemporary(const VarDecl *, raw_ostream &); - virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out); - virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out); - virtual void mangleDynamicAtExitDestructor(const VarDecl *D, - raw_ostream &Out); - -private: - void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode); -}; - } bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { @@ -267,8 +336,14 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { return true; } -void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, - StringRef Prefix) { +bool +MicrosoftMangleContextImpl::shouldMangleStringLiteral(const StringLiteral *SL) { + return SL->isAscii() || SL->isWide(); + // TODO: This needs to be updated when MSVC gains support for Unicode + // literals. +} + +void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { // MSVC doesn't mangle C++ names the same way it mangles extern "C" names. // Therefore it's really important that we don't decorate the // name with leading underscores or leading/trailing at signs. So, by @@ -286,10 +361,9 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, // TODO: Fields? Can MSVC even mangle them? // Issue a diagnostic for now. DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this declaration yet"); - Diags.Report(D->getLocation(), DiagID) - << D->getSourceRange(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "cannot mangle this declaration yet"); + Diags.Report(D->getLocation(), DiagID) << D->getSourceRange(); } } @@ -324,7 +398,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { // ::= 2 # public static member // ::= 3 # global // ::= 4 # static local - + // The first character in the encoding (after the name) is the storage class. if (VD->isStaticDataMember()) { // If it's a static member, it also encodes the access level. @@ -344,13 +418,13 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { // ::= <type> <pointee-cvr-qualifiers> # pointers, references // Pointers and references are odd. The type of 'int * const foo;' gets // mangled as 'QAHA' instead of 'PAHB', for example. - TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc(); - QualType Ty = TL.getType(); + SourceRange SR = VD->getSourceRange(); + QualType Ty = VD->getType(); if (Ty->isPointerType() || Ty->isReferenceType() || Ty->isMemberPointerType()) { - mangleType(Ty, TL.getSourceRange(), QMM_Drop); - if (PointersAre64Bit) - Out << 'E'; + mangleType(Ty, SR, QMM_Drop); + manglePointerExtQualifiers( + Ty.getDesugaredType(getASTContext()).getLocalQualifiers(), nullptr); if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) { mangleQualifiers(MPT->getPointeeType().getQualifiers(), true); // Member pointers are suffixed with a back reference to the member @@ -366,25 +440,137 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { else mangleQualifiers(Ty.getQualifiers(), false); } else { - mangleType(Ty, TL.getSourceRange(), QMM_Drop); + mangleType(Ty, SR, QMM_Drop); mangleQualifiers(Ty.getLocalQualifiers(), false); } } +void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD, + const ValueDecl *VD) { + // <member-data-pointer> ::= <integer-literal> + // ::= $F <number> <number> + // ::= $G <number> <number> <number> + + int64_t FieldOffset; + int64_t VBTableOffset; + MSInheritanceAttr::Spelling IM = RD->getMSInheritanceModel(); + if (VD) { + FieldOffset = getASTContext().getFieldOffset(VD); + assert(FieldOffset % getASTContext().getCharWidth() == 0 && + "cannot take address of bitfield"); + FieldOffset /= getASTContext().getCharWidth(); + + VBTableOffset = 0; + } else { + FieldOffset = RD->nullFieldOffsetIsZero() ? 0 : -1; + + VBTableOffset = -1; + } + + char Code = '\0'; + switch (IM) { + case MSInheritanceAttr::Keyword_single_inheritance: Code = '0'; break; + case MSInheritanceAttr::Keyword_multiple_inheritance: Code = '0'; break; + case MSInheritanceAttr::Keyword_virtual_inheritance: Code = 'F'; break; + case MSInheritanceAttr::Keyword_unspecified_inheritance: Code = 'G'; break; + } + + Out << '$' << Code; + + mangleNumber(FieldOffset); + + // The C++ standard doesn't allow base-to-derived member pointer conversions + // in template parameter contexts, so the vbptr offset of data member pointers + // is always zero. + if (MSInheritanceAttr::hasVBPtrOffsetField(IM)) + mangleNumber(0); + if (MSInheritanceAttr::hasVBTableOffsetField(IM)) + mangleNumber(VBTableOffset); +} + +void +MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD, + const CXXMethodDecl *MD) { + // <member-function-pointer> ::= $1? <name> + // ::= $H? <name> <number> + // ::= $I? <name> <number> <number> + // ::= $J? <name> <number> <number> <number> + + MSInheritanceAttr::Spelling IM = RD->getMSInheritanceModel(); + + char Code = '\0'; + switch (IM) { + case MSInheritanceAttr::Keyword_single_inheritance: Code = '1'; break; + case MSInheritanceAttr::Keyword_multiple_inheritance: Code = 'H'; break; + case MSInheritanceAttr::Keyword_virtual_inheritance: Code = 'I'; break; + case MSInheritanceAttr::Keyword_unspecified_inheritance: Code = 'J'; break; + } + + // If non-virtual, mangle the name. If virtual, mangle as a virtual memptr + // thunk. + uint64_t NVOffset = 0; + uint64_t VBTableOffset = 0; + uint64_t VBPtrOffset = 0; + if (MD) { + Out << '$' << Code << '?'; + if (MD->isVirtual()) { + MicrosoftVTableContext *VTContext = + cast<MicrosoftVTableContext>(getASTContext().getVTableContext()); + const MicrosoftVTableContext::MethodVFTableLocation &ML = + VTContext->getMethodVFTableLocation(GlobalDecl(MD)); + mangleVirtualMemPtrThunk(MD, ML); + NVOffset = ML.VFPtrOffset.getQuantity(); + VBTableOffset = ML.VBTableIndex * 4; + if (ML.VBase) { + const ASTRecordLayout &Layout = getASTContext().getASTRecordLayout(RD); + VBPtrOffset = Layout.getVBPtrOffset().getQuantity(); + } + } else { + mangleName(MD); + mangleFunctionEncoding(MD); + } + } else { + // Null single inheritance member functions are encoded as a simple nullptr. + if (IM == MSInheritanceAttr::Keyword_single_inheritance) { + Out << "$0A@"; + return; + } + if (IM == MSInheritanceAttr::Keyword_unspecified_inheritance) + VBTableOffset = -1; + Out << '$' << Code; + } + + if (MSInheritanceAttr::hasNVOffsetField(/*IsMemberFunction=*/true, IM)) + mangleNumber(NVOffset); + if (MSInheritanceAttr::hasVBPtrOffsetField(IM)) + mangleNumber(VBPtrOffset); + if (MSInheritanceAttr::hasVBTableOffsetField(IM)) + mangleNumber(VBTableOffset); +} + +void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk( + const CXXMethodDecl *MD, + const MicrosoftVTableContext::MethodVFTableLocation &ML) { + // Get the vftable offset. + CharUnits PointerWidth = getASTContext().toCharUnitsFromBits( + getASTContext().getTargetInfo().getPointerWidth(0)); + uint64_t OffsetInVFTable = ML.Index * PointerWidth.getQuantity(); + + Out << "?_9"; + mangleName(MD->getParent()); + Out << "$B"; + mangleNumber(OffsetInVFTable); + Out << 'A'; + Out << (PointersAre64Bit ? 'A' : 'E'); +} + void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) { // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @ - const DeclContext *DC = ND->getDeclContext(); // Always start with the unqualified name. - mangleUnqualifiedName(ND); - - // If this is an extern variable declared locally, the relevant DeclContext - // is that of the containing namespace, or the translation unit. - if (isa<FunctionDecl>(DC) && ND->hasLinkage()) - while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = DC->getParent(); + mangleUnqualifiedName(ND); - manglePostfix(DC); + mangleNestedName(ND); // Terminate the whole name with an '@'. Out << '@'; @@ -412,8 +598,8 @@ void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) { // in the range of ASCII characters 'A' to 'P'. // The number 0x123450 would be encoded as 'BCDEFA' char EncodedNumberBuffer[sizeof(uint64_t) * 2]; - llvm::MutableArrayRef<char> BufferRef(EncodedNumberBuffer); - llvm::MutableArrayRef<char>::reverse_iterator I = BufferRef.rbegin(); + MutableArrayRef<char> BufferRef(EncodedNumberBuffer); + MutableArrayRef<char>::reverse_iterator I = BufferRef.rbegin(); for (; Value != 0; Value >>= 4) *I++ = 'A' + (Value & 0xf); Out.write(I.base(), I - BufferRef.rbegin()); @@ -424,7 +610,7 @@ void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) { static const TemplateDecl * isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { // Check if we have a function template. - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){ + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { if (const TemplateDecl *TD = FD->getPrimaryTemplate()) { TemplateArgs = FD->getTemplateSpecializationArgs(); return TD; @@ -433,24 +619,30 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { // Check if we have a class template. if (const ClassTemplateSpecializationDecl *Spec = - dyn_cast<ClassTemplateSpecializationDecl>(ND)) { + dyn_cast<ClassTemplateSpecializationDecl>(ND)) { + TemplateArgs = &Spec->getTemplateArgs(); + return Spec->getSpecializedTemplate(); + } + + // Check if we have a variable template. + if (const VarTemplateSpecializationDecl *Spec = + dyn_cast<VarTemplateSpecializationDecl>(ND)) { TemplateArgs = &Spec->getTemplateArgs(); return Spec->getSpecializedTemplate(); } - return 0; + return nullptr; } -void -MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, - DeclarationName Name) { +void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, + DeclarationName Name) { // <unqualified-name> ::= <operator-name> // ::= <ctor-dtor-name> // ::= <source-name> // ::= <template-name> // Check if we have a template. - const TemplateArgumentList *TemplateArgs = 0; + const TemplateArgumentList *TemplateArgs = nullptr; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { // Function templates aren't considered for name back referencing. This // makes sense since function templates aren't likely to occur multiple @@ -458,10 +650,10 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // FIXME: Test alias template mangling with MSVC 2013. if (!isa<ClassTemplateDecl>(TD)) { mangleTemplateInstantiationName(TD, *TemplateArgs); + Out << '@'; return; } - // We have a class template. // Here comes the tricky thing: if we need to mangle something like // void foo(A::X<Y>, B::X<Y>), // the X<Y> part is aliased. However, if you need to mangle @@ -473,30 +665,17 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // type [ -> template-parameters] // \-> namespace[s] // What we do is we create a new mangler, mangle the same type (without - // a namespace suffix) using the extra mangler with back references - // disabled (to avoid infinite recursion) and then use the mangled type - // name as a key to check the mangling of different types for aliasing. - - std::string BackReferenceKey; - BackRefMap::iterator Found; - if (UseNameBackReferences) { - llvm::raw_string_ostream Stream(BackReferenceKey); - MicrosoftCXXNameMangler Extra(Context, Stream); - Extra.disableBackReferences(); - Extra.mangleUnqualifiedName(ND, Name); - Stream.flush(); - - Found = NameBackReferences.find(BackReferenceKey); - } - if (!UseNameBackReferences || Found == NameBackReferences.end()) { - mangleTemplateInstantiationName(TD, *TemplateArgs); - if (UseNameBackReferences && NameBackReferences.size() < 10) { - size_t Size = NameBackReferences.size(); - NameBackReferences[BackReferenceKey] = Size; - } - } else { - Out << Found->second; - } + // a namespace suffix) to a string using the extra mangler and then use + // the mangled type name as a key to check the mangling of different types + // for aliasing. + + llvm::SmallString<64> TemplateMangling; + llvm::raw_svector_ostream Stream(TemplateMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + Extra.mangleTemplateInstantiationName(TD, *TemplateArgs); + Stream.flush(); + + mangleSourceName(TemplateMangling); return; } @@ -506,17 +685,31 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, mangleSourceName(II->getName()); break; } - + // Otherwise, an anonymous entity. We must have a declaration. assert(ND && "mangling empty name without declaration"); - + if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) { if (NS->isAnonymousNamespace()) { Out << "?A@"; break; } } - + + if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) { + // We must have an anonymous union or struct declaration. + const CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl(); + assert(RD && "expected variable decl to have a record type"); + // Anonymous types with no tag or typedef get the name of their + // declarator mangled in. If they have no declarator, number them with + // a $S prefix. + llvm::SmallString<64> Name("$S"); + // Get a unique id for the anonymous struct. + Name += llvm::utostr(Context.getAnonymousStructId(RD) + 1); + mangleSourceName(Name.str()); + break; + } + // We must have an anonymous struct. const TagDecl *TD = cast<TagDecl>(ND); if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) { @@ -528,26 +721,43 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, break; } + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { + if (Record->isLambda()) { + llvm::SmallString<10> Name("<lambda_"); + unsigned LambdaId; + if (Record->getLambdaManglingNumber()) + LambdaId = Record->getLambdaManglingNumber(); + else + LambdaId = Context.getLambdaId(Record); + + Name += llvm::utostr(LambdaId); + Name += ">"; + + mangleSourceName(Name); + break; + } + } + + llvm::SmallString<64> Name("<unnamed-type-"); if (TD->hasDeclaratorForAnonDecl()) { // Anonymous types with no tag or typedef get the name of their - // declarator mangled in. - llvm::SmallString<64> Name("<unnamed-type-"); + // declarator mangled in if they have one. Name += TD->getDeclaratorForAnonDecl()->getName(); - Name += ">"; - mangleSourceName(Name.str()); } else { - // Anonymous types with no tag, no typedef, or declarator get - // '<unnamed-tag>'. - mangleSourceName("<unnamed-tag>"); + // Otherwise, number the types using a $S prefix. + Name += "$S"; + Name += llvm::utostr(Context.getAnonymousStructId(TD)); } + Name += ">"; + mangleSourceName(Name.str()); break; } - + case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: llvm_unreachable("Can't mangle Objective-C selector names here!"); - + case DeclarationName::CXXConstructorName: if (ND == Structor) { assert(StructorType == Ctor_Complete && @@ -555,7 +765,7 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } Out << "?0"; break; - + case DeclarationName::CXXDestructorName: if (ND == Structor) // If the named decl is the C++ destructor we're mangling, @@ -566,70 +776,69 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // class with a destructor is declared within a destructor. mangleCXXDtorType(Dtor_Base); break; - + case DeclarationName::CXXConversionFunctionName: // <operator-name> ::= ?B # (cast) // The target type is encoded as the return type. Out << "?B"; break; - + case DeclarationName::CXXOperatorName: mangleOperatorName(Name.getCXXOverloadedOperator(), ND->getLocation()); break; - + case DeclarationName::CXXLiteralOperatorName: { - // FIXME: Was this added in VS2010? Does MS even know how to mangle this? - DiagnosticsEngine Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this literal operator yet"); - Diags.Report(ND->getLocation(), DiagID); + Out << "?__K"; + mangleSourceName(Name.getCXXLiteralIdentifier()->getName()); break; } - + case DeclarationName::CXXUsingDirective: llvm_unreachable("Can't mangle a using directive name!"); } } -void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC, - bool NoFunction) { +void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { // <postfix> ::= <unqualified-name> [<postfix>] // ::= <substitution> [<postfix>] - - if (!DC) return; - - while (isa<LinkageSpecDecl>(DC)) - DC = DC->getParent(); - - if (DC->isTranslationUnit()) + if (isLambda(ND)) return; - if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) { - DiagnosticsEngine Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle a local inside this block yet"); - Diags.Report(BD->getLocation(), DiagID); + const DeclContext *DC = ND->getDeclContext(); - // FIXME: This is completely, utterly, wrong; see ItaniumMangle - // for how this should be done. - Out << "__block_invoke" << Context.getBlockId(BD, false); - Out << '@'; - return manglePostfix(DC->getParent(), NoFunction); - } else if (isa<CapturedDecl>(DC)) { - // Skip CapturedDecl context. - manglePostfix(DC->getParent(), NoFunction); - return; - } + while (!DC->isTranslationUnit()) { + if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) { + unsigned Disc; + if (Context.getNextDiscriminator(ND, Disc)) { + Out << '?'; + mangleNumber(Disc); + Out << '?'; + } + } - if (NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC))) - return; - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) - mangleObjCMethodName(Method); - else if (const FunctionDecl *Func = dyn_cast<FunctionDecl>(DC)) - mangleLocalName(Func); - else { - mangleUnqualifiedName(cast<NamedDecl>(DC)); - manglePostfix(DC->getParent(), NoFunction); + if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = + Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle a local inside this block yet"); + Diags.Report(BD->getLocation(), DiagID); + + // FIXME: This is completely, utterly, wrong; see ItaniumMangle + // for how this should be done. + Out << "__block_invoke" << Context.getBlockId(BD, false); + Out << '@'; + continue; + } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { + mangleObjCMethodName(Method); + } else if (isa<NamedDecl>(DC)) { + ND = cast<NamedDecl>(DC); + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { + mangle(FD, "?"); + break; + } else + mangleUnqualifiedName(ND); + } + DC = DC->getParent(); } } @@ -768,7 +977,7 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, case OO_Array_New: Out << "?_U"; break; // <operator-name> ::= ?_V # delete[] case OO_Array_Delete: Out << "?_V"; break; - + case OO_Conditional: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -776,7 +985,7 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, Diags.Report(Loc, DiagID); break; } - + case OO_None: case NUM_OVERLOADED_OPERATORS: llvm_unreachable("Not an overloaded operator"); @@ -786,14 +995,19 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, void MicrosoftCXXNameMangler::mangleSourceName(StringRef Name) { // <source name> ::= <identifier> @ BackRefMap::iterator Found; - if (UseNameBackReferences) + if (NameBackReferences.size() < 10) { + size_t Size = NameBackReferences.size(); + bool Inserted; + std::tie(Found, Inserted) = + NameBackReferences.insert(std::make_pair(Name, Size)); + if (Inserted) + Found = NameBackReferences.end(); + } else { Found = NameBackReferences.find(Name); - if (!UseNameBackReferences || Found == NameBackReferences.end()) { + } + + if (Found == NameBackReferences.end()) { Out << Name << '@'; - if (UseNameBackReferences && NameBackReferences.size() < 10) { - size_t Size = NameBackReferences.size(); - NameBackReferences[Name] = Size; - } } else { Out << Found->second; } @@ -803,47 +1017,8 @@ void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { Context.mangleObjCMethodName(MD, Out); } -// Find out how many function decls live above this one and return an integer -// suitable for use as the number in a numbered anonymous scope. -// TODO: Memoize. -static unsigned getLocalNestingLevel(const FunctionDecl *FD) { - const DeclContext *DC = FD->getParent(); - int level = 1; - - while (DC && !DC->isTranslationUnit()) { - if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) level++; - DC = DC->getParent(); - } - - return 2*level; -} - -void MicrosoftCXXNameMangler::mangleLocalName(const FunctionDecl *FD) { - // <nested-name> ::= <numbered-anonymous-scope> ? <mangled-name> - // <numbered-anonymous-scope> ::= ? <number> - // Even though the name is rendered in reverse order (e.g. - // A::B::C is rendered as C@B@A), VC numbers the scopes from outermost to - // innermost. So a method bar in class C local to function foo gets mangled - // as something like: - // ?bar@C@?1??foo@@YAXXZ@QAEXXZ - // This is more apparent when you have a type nested inside a method of a - // type nested inside a function. A method baz in class D local to method - // bar of class C local to function foo gets mangled as: - // ?baz@D@?3??bar@C@?1??foo@@YAXXZ@QAEXXZ@QAEXXZ - // This scheme is general enough to support GCC-style nested - // functions. You could have a method baz of class C inside a function bar - // inside a function foo, like so: - // ?baz@C@?3??bar@?1??foo@@YAXXZ@YAXXZ@QAEXXZ - unsigned NestLevel = getLocalNestingLevel(FD); - Out << '?'; - mangleNumber(NestLevel); - Out << '?'; - mangle(FD, "?"); -} - void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( - const TemplateDecl *TD, - const TemplateArgumentList &TemplateArgs) { + const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) { // <template-name> ::= <unscoped-template-name> <template-args> // ::= <substitution> // Always start with the unqualified name. @@ -869,9 +1044,8 @@ MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) { mangleUnqualifiedName(TD); } -void -MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, - bool IsBoolean) { +void MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, + bool IsBoolean) { // <integer-literal> ::= $0 <number> Out << "$0"; // Make sure booleans are encoded as 0/1. @@ -881,8 +1055,7 @@ MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, mangleNumber(Value.getSExtValue()); } -void -MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { +void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { // See if this is a constant expression. llvm::APSInt Value; if (E->isIntegerConstantExpr(Value, Context.getASTContext())) { @@ -890,7 +1063,10 @@ MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { return; } - const CXXUuidofExpr *UE = 0; + // Look through no-op casts like template parameter substitutions. + E = E->IgnoreParenNoopCasts(Context.getASTContext()); + + const CXXUuidofExpr *UE = nullptr; if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { if (UO->getOpcode() == UO_AddrOf) UE = dyn_cast<CXXUuidofExpr>(UO->getSubExpr()); @@ -919,26 +1095,30 @@ MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { // As bad as this diagnostic is, it's better than crashing. DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot yet mangle expression type %0"); - Diags.Report(E->getExprLoc(), DiagID) - << E->getStmtClassName() << E->getSourceRange(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "cannot yet mangle expression type %0"); + Diags.Report(E->getExprLoc(), DiagID) << E->getStmtClassName() + << E->getSourceRange(); } -void -MicrosoftCXXNameMangler::mangleTemplateArgs(const TemplateDecl *TD, - const TemplateArgumentList &TemplateArgs) { - // <template-args> ::= {<type> | <integer-literal>}+ @ - unsigned NumTemplateArgs = TemplateArgs.size(); - for (unsigned i = 0; i < NumTemplateArgs; ++i) { - const TemplateArgument &TA = TemplateArgs[i]; +void MicrosoftCXXNameMangler::mangleTemplateArgs( + const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) { + // <template-args> ::= <template-arg>+ + for (const TemplateArgument &TA : TemplateArgs.asArray()) mangleTemplateArg(TD, TA); - } - Out << '@'; } void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA) { + // <template-arg> ::= <type> + // ::= <integer-literal> + // ::= <member-data-pointer> + // ::= <member-function-pointer> + // ::= $E? <name> <type-encoding> + // ::= $1? <name> <type-encoding> + // ::= $0A@ + // ::= <template-args> + switch (TA.getKind()) { case TemplateArgument::Null: llvm_unreachable("Can't mangle null template arguments!"); @@ -951,25 +1131,54 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, } case TemplateArgument::Declaration: { const NamedDecl *ND = cast<NamedDecl>(TA.getAsDecl()); - mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?"); + if (isa<FieldDecl>(ND) || isa<IndirectFieldDecl>(ND)) { + mangleMemberDataPointer( + cast<CXXRecordDecl>(ND->getDeclContext())->getMostRecentDecl(), + cast<ValueDecl>(ND)); + } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); + if (MD && MD->isInstance()) + mangleMemberFunctionPointer(MD->getParent()->getMostRecentDecl(), MD); + else + mangle(FD, "$1?"); + } else { + mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?"); + } break; } case TemplateArgument::Integral: mangleIntegerLiteral(TA.getAsIntegral(), TA.getIntegralType()->isBooleanType()); break; - case TemplateArgument::NullPtr: + case TemplateArgument::NullPtr: { + QualType T = TA.getNullPtrType(); + if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) { + const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); + if (MPT->isMemberFunctionPointerType() && isa<ClassTemplateDecl>(TD)) { + mangleMemberFunctionPointer(RD, nullptr); + return; + } + if (MPT->isMemberDataPointer()) { + mangleMemberDataPointer(RD, nullptr); + return; + } + } Out << "$0A@"; break; + } case TemplateArgument::Expression: mangleExpression(TA.getAsExpr()); break; - case TemplateArgument::Pack: - // Unlike Itanium, there is no character code to indicate an argument pack. - for (TemplateArgument::pack_iterator I = TA.pack_begin(), E = TA.pack_end(); - I != E; ++I) - mangleTemplateArg(TD, *I); + case TemplateArgument::Pack: { + ArrayRef<TemplateArgument> TemplateArgs = TA.getPackAsArray(); + if (TemplateArgs.empty()) { + Out << "$S"; + } else { + for (const TemplateArgument &PA : TemplateArgs) + mangleTemplateArg(TD, PA); + } break; + } case TemplateArgument::Template: mangleType(cast<TagDecl>( TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl())); @@ -1059,13 +1268,43 @@ void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, // FIXME: For now, just drop all extension qualifiers on the floor. } -void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) { - // <pointer-cvr-qualifiers> ::= P # no qualifiers - // ::= Q # const - // ::= R # volatile - // ::= S # const volatile +void +MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) { + // <ref-qualifier> ::= G # lvalue reference + // ::= H # rvalue-reference + switch (RefQualifier) { + case RQ_None: + break; + + case RQ_LValue: + Out << 'G'; + break; + + case RQ_RValue: + Out << 'H'; + break; + } +} + +void +MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals, + const Type *PointeeType) { + bool HasRestrict = Quals.hasRestrict(); + if (PointersAre64Bit && (!PointeeType || !PointeeType->isFunctionType())) + Out << 'E'; + + if (HasRestrict) + Out << 'I'; +} + +void MicrosoftCXXNameMangler::manglePointerCVQualifiers(Qualifiers Quals) { + // <pointer-cv-qualifiers> ::= P # no qualifiers + // ::= Q # const + // ::= R # volatile + // ::= S # const volatile bool HasConst = Quals.hasConst(), HasVolatile = Quals.hasVolatile(); + if (HasConst && HasVolatile) { Out << 'S'; } else if (HasVolatile) { @@ -1165,8 +1404,10 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, } // We have to mangle these now, while we still have enough information. - if (IsPointer) - manglePointerQualifiers(Quals); + if (IsPointer) { + manglePointerCVQualifiers(Quals); + manglePointerExtQualifiers(Quals, T->getPointeeType().getTypePtr()); + } const Type *ty = T.getTypePtr(); switch (ty->getTypeClass()) { @@ -1254,7 +1495,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, case BuiltinType::OCLImage3d: Out << "PAUocl_image3d@@"; break; case BuiltinType::OCLSampler: Out << "PAUocl_sampler@@"; break; case BuiltinType::OCLEvent: Out << "PAUocl_event@@"; break; - + case BuiltinType::NullPtr: Out << "$$T"; break; case BuiltinType::Char16: @@ -1306,9 +1547,10 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. if (IsInstMethod) { - if (PointersAre64Bit) - Out << 'E'; - mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false); + Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals()); + manglePointerExtQualifiers(Quals, nullptr); + mangleRefQualifier(Proto->getRefQualifier()); + mangleQualifiers(Quals, false); } mangleCallingConvention(T); @@ -1327,23 +1569,30 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, } Out << '@'; } else { - QualType ResultType = Proto->getResultType(); - if (ResultType->isVoidType()) - ResultType = ResultType.getUnqualifiedType(); - mangleType(ResultType, Range, QMM_Result); + QualType ResultType = Proto->getReturnType(); + if (const auto *AT = + dyn_cast_or_null<AutoType>(ResultType->getContainedAutoType())) { + Out << '?'; + mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false); + Out << '?'; + mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>"); + Out << '@'; + } else { + if (ResultType->isVoidType()) + ResultType = ResultType.getUnqualifiedType(); + mangleType(ResultType, Range, QMM_Result); + } } // <argument-list> ::= X # void // ::= <type>+ @ // ::= <type>* Z # varargs - if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) { + if (Proto->getNumParams() == 0 && !Proto->isVariadic()) { Out << 'X'; } else { // Happens for function pointer type arguments for example. - for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), - ArgEnd = Proto->arg_type_end(); - Arg != ArgEnd; ++Arg) - mangleArgumentType(*Arg, Range); + for (const QualType Arg : Proto->param_types()) + mangleArgumentType(Arg, Range); // <builtin-type> ::= Z # ellipsis if (Proto->isVariadic()) Out << 'Z'; @@ -1465,7 +1714,7 @@ void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T, // <union-type> ::= T <name> // <struct-type> ::= U <name> // <class-type> ::= V <name> -// <enum-type> ::= W <size> <name> +// <enum-type> ::= W4 <name> void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) { mangleType(cast<TagType>(T)->getDecl()); } @@ -1485,9 +1734,7 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { Out << 'V'; break; case TTK_Enum: - Out << 'W'; - Out << getASTContext().getTypeSizeInChars( - cast<EnumDecl>(TD)->getIntegerType()).getQuantity(); + Out << "W4"; break; } mangleName(TD); @@ -1503,7 +1750,7 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T) { // This isn't a recursive mangling, so now we have to do it all in this // one call. - manglePointerQualifiers(T->getElementType().getQualifiers()); + manglePointerCVQualifiers(T->getElementType().getQualifiers()); mangleType(T->getElementType(), SourceRange()); } void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T, @@ -1527,7 +1774,7 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { SmallVector<llvm::APInt, 3> Dimensions; for (;;) { if (const ConstantArrayType *CAT = - getASTContext().getAsConstantArrayType(ElementTy)) { + getASTContext().getAsConstantArrayType(ElementTy)) { Dimensions.push_back(CAT->getSize()); ElementTy = CAT->getElementType(); } else if (ElementTy->isVariableArrayType()) { @@ -1550,7 +1797,7 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { << DSAT->getBracketsRange(); return; } else if (const IncompleteArrayType *IAT = - getASTContext().getAsIncompleteArrayType(ElementTy)) { + getASTContext().getAsIncompleteArrayType(ElementTy)) { Dimensions.push_back(llvm::APInt(32, 0)); ElementTy = IAT->getElementType(); } @@ -1559,8 +1806,8 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { Out << 'Y'; // <dimension-count> ::= <number> # number of extra dimensions mangleNumber(Dimensions.size()); - for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) - mangleNumber(Dimensions[Dim].getLimitedValue()); + for (const llvm::APInt &Dimension : Dimensions) + mangleNumber(Dimension.getLimitedValue()); mangleType(ElementTy, SourceRange(), QMM_Escape); } @@ -1573,10 +1820,8 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T, if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) { Out << '8'; mangleName(T->getClass()->castAs<RecordType>()->getDecl()); - mangleFunctionType(FPT, 0, true); + mangleFunctionType(FPT, nullptr, true); } else { - if (PointersAre64Bit && !T->getPointeeType()->isFunctionType()) - Out << 'E'; mangleQualifiers(PointeeType.getQualifiers(), true); mangleName(T->getClass()->castAs<RecordType>()->getDecl()); mangleType(PointeeType, Range, QMM_Drop); @@ -1604,42 +1849,37 @@ void MicrosoftCXXNameMangler::mangleType( // <type> ::= <pointer-type> // <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type> -// # the E is required for 64-bit non static pointers +// # the E is required for 64-bit non-static pointers void MicrosoftCXXNameMangler::mangleType(const PointerType *T, SourceRange Range) { QualType PointeeTy = T->getPointeeType(); - if (PointersAre64Bit && !T->getPointeeType()->isFunctionType()) - Out << 'E'; mangleType(PointeeTy, Range); } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, SourceRange Range) { // Object pointers never have qualifiers. Out << 'A'; - if (PointersAre64Bit && !T->getPointeeType()->isFunctionType()) - Out << 'E'; + manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr()); mangleType(T->getPointeeType(), Range); } // <type> ::= <reference-type> // <reference-type> ::= A E? <cvr-qualifiers> <type> -// # the E is required for 64-bit non static lvalue references +// # the E is required for 64-bit non-static lvalue references void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T, SourceRange Range) { Out << 'A'; - if (PointersAre64Bit && !T->getPointeeType()->isFunctionType()) - Out << 'E'; + manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr()); mangleType(T->getPointeeType(), Range); } // <type> ::= <r-value-reference-type> // <r-value-reference-type> ::= $$Q E? <cvr-qualifiers> <type> -// # the E is required for 64-bit non static rvalue references +// # the E is required for 64-bit non-static rvalue references void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T, SourceRange Range) { Out << "$$Q"; - if (PointersAre64Bit && !T->getPointeeType()->isFunctionType()) - Out << 'E'; + manglePointerExtQualifiers(Qualifiers(), T->getPointeeType().getTypePtr()); mangleType(T->getPointeeType(), Range); } @@ -1804,6 +2044,8 @@ void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T, } void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) { + assert(T->getDeducedType().isNull() && "expecting a dependent type!"); + DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this 'auto' type yet"); @@ -1923,17 +2165,17 @@ static void mangleThunkThisAdjustment(const CXXMethodDecl *MD, } } -void MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk( - const CXXMethodDecl *MD, uint64_t OffsetInVFTable, raw_ostream &Out) { - bool Is64Bit = getASTContext().getTargetInfo().getPointerWidth(0) == 64; +void +MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, + raw_ostream &Out) { + MicrosoftVTableContext *VTContext = + cast<MicrosoftVTableContext>(getASTContext().getVTableContext()); + const MicrosoftVTableContext::MethodVFTableLocation &ML = + VTContext->getMethodVFTableLocation(GlobalDecl(MD)); MicrosoftCXXNameMangler Mangler(*this, Out); - Mangler.getStream() << "\01??_9"; - Mangler.mangleName(MD->getParent()); - Mangler.getStream() << "$B"; - Mangler.mangleNumber(OffsetInVFTable); - Mangler.getStream() << "A"; - Mangler.getStream() << (Is64Bit ? "A" : "E"); + Mangler.getStream() << "\01?"; + Mangler.mangleVirtualMemPtrThunk(MD, ML); } void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD, @@ -1944,7 +2186,8 @@ void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD, Mangler.mangleName(MD); mangleThunkThisAdjustment(MD, Thunk.This, Mangler, Out); if (!Thunk.Return.isEmpty()) - assert(Thunk.Method != 0 && "Thunk info should hold the overridee decl"); + assert(Thunk.Method != nullptr && + "Thunk info should hold the overridee decl"); const CXXMethodDecl *DeclForFPT = Thunk.Method ? Thunk.Method : MD; Mangler.mangleFunctionType( @@ -1976,11 +2219,8 @@ void MicrosoftMangleContextImpl::mangleCXXVFTable( Mangler.getStream() << "\01??_7"; Mangler.mangleName(Derived); Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const. - for (ArrayRef<const CXXRecordDecl *>::iterator I = BasePath.begin(), - E = BasePath.end(); - I != E; ++I) { - Mangler.mangleName(*I); - } + for (const CXXRecordDecl *RD : BasePath) + Mangler.mangleName(RD); Mangler.getStream() << '@'; } @@ -1995,28 +2235,68 @@ void MicrosoftMangleContextImpl::mangleCXXVBTable( Mangler.getStream() << "\01??_8"; Mangler.mangleName(Derived); Mangler.getStream() << "7B"; // '7' for vbtable, 'B' for const. - for (ArrayRef<const CXXRecordDecl *>::iterator I = BasePath.begin(), - E = BasePath.end(); - I != E; ++I) { - Mangler.mangleName(*I); - } + for (const CXXRecordDecl *RD : BasePath) + Mangler.mangleName(RD); Mangler.getStream() << '@'; } -void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &) { - // FIXME: Give a location... - unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle RTTI descriptors for type %0 yet"); - getDiags().Report(DiagID) - << T.getBaseTypeIdentifier(); +void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_R0"; + Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); + Mangler.getStream() << "@8"; } -void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, raw_ostream &) { - // FIXME: Give a location... - unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle the name of type %0 into RTTI descriptors yet"); - getDiags().Report(DiagID) - << T.getBaseTypeIdentifier(); +void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, + raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << '.'; + Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); +} + +void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor( + const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset, + uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_R1"; + Mangler.mangleNumber(NVOffset); + Mangler.mangleNumber(VBPtrOffset); + Mangler.mangleNumber(VBTableOffset); + Mangler.mangleNumber(Flags); + Mangler.mangleName(Derived); + Mangler.getStream() << "8"; +} + +void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray( + const CXXRecordDecl *Derived, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_R2"; + Mangler.mangleName(Derived); + Mangler.getStream() << "8"; +} + +void MicrosoftMangleContextImpl::mangleCXXRTTIClassHierarchyDescriptor( + const CXXRecordDecl *Derived, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_R3"; + Mangler.mangleName(Derived); + Mangler.getStream() << "8"; +} + +void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator( + const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath, + raw_ostream &Out) { + // <mangled-name> ::= ?_R4 <class-name> <storage-class> + // <cvr-qualifiers> [<name>] @ + // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class> + // is always '6' for vftables. + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_R4"; + Mangler.mangleName(Derived); + Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const. + for (const CXXRecordDecl *RD : BasePath) + Mangler.mangleName(RD); + Mangler.getStream() << '@'; } void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) { @@ -2042,6 +2322,7 @@ void MicrosoftMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D, } void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD, + unsigned, raw_ostream &) { unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this reference temporary yet"); @@ -2050,7 +2331,16 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD, void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, raw_ostream &Out) { - // <guard-name> ::= ?_B <postfix> @51 + // TODO: This is not correct, especially with respect to MSVC2013. MSVC2013 + // utilizes thread local variables to implement thread safe, re-entrant + // initialization for statics. They no longer differentiate between an + // externally visible and non-externally visible static with respect to + // mangling, they all get $TSS <number>. + // + // N.B. This means that they can get more than 32 static variable guards in a + // scope. It also means that they broke compatibility with their own ABI. + + // <guard-name> ::= ?_B <postfix> @5 <scope-depth> // ::= ?$S <guard-num> @ <postfix> @4IA // The first mangling is what MSVC uses to guard static locals in inline @@ -2064,8 +2354,17 @@ void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, bool Visible = VD->isExternallyVisible(); // <operator-name> ::= ?_B # local static guard Mangler.getStream() << (Visible ? "\01??_B" : "\01?$S1@"); - Mangler.manglePostfix(VD->getDeclContext()); - Mangler.getStream() << (Visible ? "@51" : "@4IA"); + unsigned ScopeDepth = 0; + if (Visible && !getNextDiscriminator(VD, ScopeDepth)) + // If we do not have a discriminator and are emitting a guard variable for + // use at global scope, then mangling the nested name will not be enough to + // remove ambiguities. + Mangler.mangle(VD, ""); + else + Mangler.mangleNestedName(VD); + Mangler.getStream() << (Visible ? "@5" : "@4IA"); + if (ScopeDepth) + Mangler.mangleNumber(ScopeDepth); } void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D, @@ -2074,6 +2373,10 @@ void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D, MicrosoftCXXNameMangler Mangler(*this, Out); Mangler.getStream() << "\01??__" << CharCode; Mangler.mangleName(D); + if (D->isStaticDataMember()) { + Mangler.mangleVariableEncoding(D); + Mangler.getStream() << '@'; + } // This is the function class mangling. These stubs are global, non-variadic, // cdecl functions that return void and take no args. Mangler.getStream() << "YAXXZ"; @@ -2092,6 +2395,172 @@ MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D, mangleInitFiniStub(D, Out, 'F'); } +void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, + raw_ostream &Out) { + // <char-type> ::= 0 # char + // ::= 1 # wchar_t + // ::= ??? # char16_t/char32_t will need a mangling too... + // + // <literal-length> ::= <non-negative integer> # the length of the literal + // + // <encoded-crc> ::= <hex digit>+ @ # crc of the literal including + // # null-terminator + // + // <encoded-string> ::= <simple character> # uninteresting character + // ::= '?$' <hex digit> <hex digit> # these two nibbles + // # encode the byte for the + // # character + // ::= '?' [a-z] # \xe1 - \xfa + // ::= '?' [A-Z] # \xc1 - \xda + // ::= '?' [0-9] # [,/\:. \n\t'-] + // + // <literal> ::= '??_C@_' <char-type> <literal-length> <encoded-crc> + // <encoded-string> '@' + MicrosoftCXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "\01??_C@_"; + + // <char-type>: The "kind" of string literal is encoded into the mangled name. + // TODO: This needs to be updated when MSVC gains support for unicode + // literals. + if (SL->isAscii()) + Mangler.getStream() << '0'; + else if (SL->isWide()) + Mangler.getStream() << '1'; + else + llvm_unreachable("unexpected string literal kind!"); + + // <literal-length>: The next part of the mangled name consists of the length + // of the string. + // The StringLiteral does not consider the NUL terminator byte(s) but the + // mangling does. + // N.B. The length is in terms of bytes, not characters. + Mangler.mangleNumber(SL->getByteLength() + SL->getCharByteWidth()); + + // We will use the "Rocksoft^tm Model CRC Algorithm" to describe the + // properties of our CRC: + // Width : 32 + // Poly : 04C11DB7 + // Init : FFFFFFFF + // RefIn : True + // RefOut : True + // XorOut : 00000000 + // Check : 340BC6D9 + uint32_t CRC = 0xFFFFFFFFU; + + auto UpdateCRC = [&CRC](char Byte) { + for (unsigned i = 0; i < 8; ++i) { + bool Bit = CRC & 0x80000000U; + if (Byte & (1U << i)) + Bit = !Bit; + CRC <<= 1; + if (Bit) + CRC ^= 0x04C11DB7U; + } + }; + + auto GetLittleEndianByte = [&Mangler, &SL](unsigned Index) { + unsigned CharByteWidth = SL->getCharByteWidth(); + uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth); + unsigned OffsetInCodeUnit = Index % CharByteWidth; + return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff); + }; + + auto GetBigEndianByte = [&Mangler, &SL](unsigned Index) { + unsigned CharByteWidth = SL->getCharByteWidth(); + uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth); + unsigned OffsetInCodeUnit = (CharByteWidth - 1) - (Index % CharByteWidth); + return static_cast<char>((CodeUnit >> (8 * OffsetInCodeUnit)) & 0xff); + }; + + // CRC all the bytes of the StringLiteral. + for (unsigned I = 0, E = SL->getByteLength(); I != E; ++I) + UpdateCRC(GetLittleEndianByte(I)); + + // The NUL terminator byte(s) were not present earlier, + // we need to manually process those bytes into the CRC. + for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth(); + ++NullTerminator) + UpdateCRC('\x00'); + + // The literature refers to the process of reversing the bits in the final CRC + // output as "reflection". + CRC = llvm::reverseBits(CRC); + + // <encoded-crc>: The CRC is encoded utilizing the standard number mangling + // scheme. + Mangler.mangleNumber(CRC); + + // <encoded-string>: The mangled name also contains the first 32 _characters_ + // (including null-terminator bytes) of the StringLiteral. + // Each character is encoded by splitting them into bytes and then encoding + // the constituent bytes. + auto MangleByte = [&Mangler](char Byte) { + // There are five different manglings for characters: + // - [a-zA-Z0-9_$]: A one-to-one mapping. + // - ?[a-z]: The range from \xe1 to \xfa. + // - ?[A-Z]: The range from \xc1 to \xda. + // - ?[0-9]: The set of [,/\:. \n\t'-]. + // - ?$XX: A fallback which maps nibbles. + if (isIdentifierBody(Byte, /*AllowDollar=*/true)) { + Mangler.getStream() << Byte; + } else if (isLetter(Byte & 0x7f)) { + Mangler.getStream() << '?' << static_cast<char>(Byte & 0x7f); + } else { + switch (Byte) { + case ',': + Mangler.getStream() << "?0"; + break; + case '/': + Mangler.getStream() << "?1"; + break; + case '\\': + Mangler.getStream() << "?2"; + break; + case ':': + Mangler.getStream() << "?3"; + break; + case '.': + Mangler.getStream() << "?4"; + break; + case ' ': + Mangler.getStream() << "?5"; + break; + case '\n': + Mangler.getStream() << "?6"; + break; + case '\t': + Mangler.getStream() << "?7"; + break; + case '\'': + Mangler.getStream() << "?8"; + break; + case '-': + Mangler.getStream() << "?9"; + break; + default: + Mangler.getStream() << "?$"; + Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf)); + Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf)); + break; + } + } + }; + + // Enforce our 32 character max. + unsigned NumCharsToMangle = std::min(32U, SL->getLength()); + for (unsigned I = 0, E = NumCharsToMangle * SL->getCharByteWidth(); I != E; + ++I) + MangleByte(GetBigEndianByte(I)); + + // Encode the NUL terminator if there is room. + if (NumCharsToMangle < 32) + for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth(); + ++NullTerminator) + MangleByte(0); + + Mangler.getStream() << '@'; +} + MicrosoftMangleContext * MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) { return new MicrosoftMangleContextImpl(Context, Diags); diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp index a862630..986b3b5 100644 --- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp @@ -14,9 +14,9 @@ using namespace clang; NSAPI::NSAPI(ASTContext &ctx) - : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0), - NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) { -} + : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr), + NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr), + NSUTF8StringEncodingId(nullptr) {} IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const { static const char *ClassName[NumClassIds] = { diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index b03c4e0..1f041aa 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -30,7 +30,7 @@ NestedNameSpecifier::FindOrInsert(const ASTContext &Context, llvm::FoldingSetNodeID ID; Mockup.Profile(ID); - void *InsertPos = 0; + void *InsertPos = nullptr; NestedNameSpecifier *NNS = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); if (!NNS) { @@ -61,7 +61,8 @@ NestedNameSpecifier::Create(const ASTContext &Context, const NamespaceDecl *NS) { assert(NS && "Namespace cannot be NULL"); assert((!Prefix || - (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && + (Prefix->getAsType() == nullptr && + Prefix->getAsIdentifier() == nullptr)) && "Broken nested name specifier"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); @@ -76,7 +77,8 @@ NestedNameSpecifier::Create(const ASTContext &Context, NamespaceAliasDecl *Alias) { assert(Alias && "Namespace alias cannot be NULL"); assert((!Prefix || - (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && + (Prefix->getAsType() == nullptr && + Prefix->getAsIdentifier() == nullptr)) && "Broken nested name specifier"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); @@ -101,7 +103,7 @@ NestedNameSpecifier * NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { assert(II && "Identifier cannot be NULL"); NestedNameSpecifier Mockup; - Mockup.Prefix.setPointer(0); + Mockup.Prefix.setPointer(nullptr); Mockup.Prefix.setInt(StoredIdentifier); Mockup.Specifier = II; return FindOrInsert(Context, Mockup); @@ -117,7 +119,7 @@ NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { } NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { - if (Specifier == 0) + if (!Specifier) return Global; switch (Prefix.getInt()) { @@ -144,7 +146,7 @@ NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { if (Prefix.getInt() == StoredNamespaceOrAlias) return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); - return 0; + return nullptr; } /// \brief Retrieve the namespace alias stored in this nested name @@ -153,7 +155,7 @@ NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { if (Prefix.getInt() == StoredNamespaceOrAlias) return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); - return 0; + return nullptr; } @@ -437,7 +439,7 @@ namespace { NestedNameSpecifierLocBuilder:: NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) - : Representation(Other.Representation), Buffer(0), + : Representation(Other.Representation), Buffer(nullptr), BufferSize(0), BufferCapacity(0) { if (!Other.Buffer) @@ -451,10 +453,8 @@ NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) } // Deep copy - BufferSize = Other.BufferSize; - BufferCapacity = Other.BufferSize; - Buffer = static_cast<char *>(malloc(BufferCapacity)); - memcpy(Buffer, Other.Buffer, BufferSize); + Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, + BufferCapacity); } NestedNameSpecifierLocBuilder & @@ -477,7 +477,7 @@ operator=(const NestedNameSpecifierLocBuilder &Other) { if (!Other.Buffer) { // Empty. - Buffer = 0; + Buffer = nullptr; BufferSize = 0; return *this; } @@ -490,10 +490,8 @@ operator=(const NestedNameSpecifierLocBuilder &Other) { } // Deep copy. - BufferSize = Other.BufferSize; - BufferCapacity = BufferSize; - Buffer = static_cast<char *>(malloc(BufferSize)); - memcpy(Buffer, Other.Buffer, BufferSize); + Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, + BufferCapacity); return *this; } @@ -599,7 +597,7 @@ void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { free(Buffer); if (!Other) { - Representation = 0; + Representation = nullptr; BufferSize = 0; return; } diff --git a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp index ff44d93..a991302 100644 --- a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp @@ -37,7 +37,7 @@ static void BuildParentMap(MapTy& M, Stmt* S, // If we are rebuilding the map, clear out any existing state. if (M[POE->getSyntacticForm()]) for (Stmt::child_range I = S->children(); I; ++I) - M[*I] = 0; + M[*I] = nullptr; M[POE->getSyntacticForm()] = S; BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent); @@ -92,7 +92,7 @@ static void BuildParentMap(MapTy& M, Stmt* S, } } -ParentMap::ParentMap(Stmt* S) : Impl(0) { +ParentMap::ParentMap(Stmt *S) : Impl(nullptr) { if (S) { MapTy *M = new MapTy(); BuildParentMap(*M, S); @@ -120,7 +120,7 @@ void ParentMap::setParent(const Stmt *S, const Stmt *Parent) { Stmt* ParentMap::getParent(Stmt* S) const { MapTy* M = (MapTy*) Impl; MapTy::iterator I = M->find(S); - return I == M->end() ? 0 : I->second; + return I == M->end() ? nullptr : I->second; } Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const { @@ -146,7 +146,7 @@ Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const { } Stmt *ParentMap::getOuterParenParent(Stmt *S) const { - Stmt *Paren = 0; + Stmt *Paren = nullptr; while (isa<ParenExpr>(S)) { Paren = S; S = getParent(S); diff --git a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp index 1fa7cea..24b129a 100644 --- a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp @@ -95,10 +95,9 @@ StringRef RawComment::getRawTextSlow(const SourceManager &SourceMgr) const { unsigned BeginOffset; unsigned EndOffset; - llvm::tie(BeginFileID, BeginOffset) = + std::tie(BeginFileID, BeginOffset) = SourceMgr.getDecomposedLoc(Range.getBegin()); - llvm::tie(EndFileID, EndOffset) = - SourceMgr.getDecomposedLoc(Range.getEnd()); + std::tie(EndFileID, EndOffset) = SourceMgr.getDecomposedLoc(Range.getEnd()); const unsigned Length = EndOffset - BeginOffset; if (Length < 2) @@ -252,3 +251,15 @@ void RawCommentList::addComment(const RawComment &RC, Comments.push_back(new (Allocator) RawComment(RC)); } } + +void RawCommentList::addDeserializedComments(ArrayRef<RawComment *> DeserializedComments) { + std::vector<RawComment *> MergedComments; + MergedComments.reserve(Comments.size() + DeserializedComments.size()); + + std::merge(Comments.begin(), Comments.end(), + DeserializedComments.begin(), DeserializedComments.end(), + std::back_inserter(MergedComments), + BeforeThanCompare<RawComment>(SourceMgr)); + std::swap(Comments, MergedComments); +} + diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp index 71e44ec..b2c244e 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp @@ -21,19 +21,22 @@ void ASTRecordLayout::Destroy(ASTContext &Ctx) { if (FieldOffsets) Ctx.Deallocate(FieldOffsets); if (CXXInfo) { - Ctx.Deallocate(CXXInfo); CXXInfo->~CXXRecordLayoutInfo(); + Ctx.Deallocate(CXXInfo); } this->~ASTRecordLayout(); Ctx.Deallocate(this); } ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size, - CharUnits alignment, CharUnits datasize, + CharUnits alignment, + CharUnits requiredAlignment, + CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount) - : Size(size), DataSize(datasize), Alignment(alignment), FieldOffsets(0), - FieldCount(fieldcount), CXXInfo(0) { + : Size(size), DataSize(datasize), Alignment(alignment), + RequiredAlignment(requiredAlignment), FieldOffsets(nullptr), + FieldCount(fieldcount), CXXInfo(nullptr) { if (FieldCount > 0) { FieldOffsets = new (Ctx) uint64_t[FieldCount]; memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets)); @@ -43,21 +46,24 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size, // Constructor for C++ records. ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, + CharUnits requiredAlignment, bool hasOwnVFPtr, bool hasExtendableVFPtr, CharUnits vbptroffset, CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount, CharUnits nonvirtualsize, - CharUnits nonvirtualalign, + CharUnits nonvirtualalignment, CharUnits SizeOfLargestEmptySubobject, const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual, const CXXRecordDecl *BaseSharingVBPtr, - bool AlignAfterVBases, + bool HasZeroSizedSubObject, + bool LeadsWithZeroSizedBase, const BaseOffsetsMapTy& BaseOffsets, const VBaseOffsetsMapTy& VBaseOffsets) - : Size(size), DataSize(datasize), Alignment(alignment), FieldOffsets(0), + : Size(size), DataSize(datasize), Alignment(alignment), + RequiredAlignment(requiredAlignment), FieldOffsets(nullptr), FieldCount(fieldcount), CXXInfo(new (Ctx) CXXRecordLayoutInfo) { if (FieldCount > 0) { @@ -68,7 +74,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CXXInfo->PrimaryBase.setPointer(PrimaryBase); CXXInfo->PrimaryBase.setInt(IsPrimaryBaseVirtual); CXXInfo->NonVirtualSize = nonvirtualsize; - CXXInfo->NonVirtualAlign = nonvirtualalign; + CXXInfo->NonVirtualAlignment = nonvirtualalignment; CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject; CXXInfo->BaseOffsets = BaseOffsets; CXXInfo->VBaseOffsets = VBaseOffsets; @@ -76,7 +82,8 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CXXInfo->VBPtrOffset = vbptroffset; CXXInfo->HasExtendableVFPtr = hasExtendableVFPtr; CXXInfo->BaseSharingVBPtr = BaseSharingVBPtr; - CXXInfo->AlignAfterVBases = AlignAfterVBases; + CXXInfo->HasZeroSizedSubObject = HasZeroSizedSubObject; + CXXInfo->LeadsWithZeroSizedBase = LeadsWithZeroSizedBase; #ifndef NDEBUG diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index 4390e66..b3deeba 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -65,7 +65,7 @@ class EmptySubobjectMap { const CXXRecordDecl *Class; /// EmptyClassOffsets - A map from offsets to empty record decls. - typedef SmallVector<const CXXRecordDecl *, 1> ClassVectorTy; + typedef llvm::TinyPtrVector<const CXXRecordDecl *> ClassVectorTy; typedef llvm::DenseMap<CharUnits, ClassVectorTy> EmptyClassOffsetsMapTy; EmptyClassOffsetsMapTy EmptyClassOffsets; @@ -140,10 +140,8 @@ public: void EmptySubobjectMap::ComputeEmptySubobjectSizes() { // Check the bases. - for (CXXRecordDecl::base_class_const_iterator I = Class->bases_begin(), - E = Class->bases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + for (const CXXBaseSpecifier &Base : Class->bases()) { + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); CharUnits EmptySize; const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl); @@ -160,18 +158,16 @@ void EmptySubobjectMap::ComputeEmptySubobjectSizes() { } // Check the fields. - for (CXXRecordDecl::field_iterator I = Class->field_begin(), - E = Class->field_end(); I != E; ++I) { - + for (const FieldDecl *FD : Class->fields()) { const RecordType *RT = - Context.getBaseElementType(I->getType())->getAs<RecordType>(); + Context.getBaseElementType(FD->getType())->getAs<RecordType>(); // We only care about record types. if (!RT) continue; CharUnits EmptySize; - const CXXRecordDecl *MemberDecl = cast<CXXRecordDecl>(RT->getDecl()); + const CXXRecordDecl *MemberDecl = RT->getAsCXXRecordDecl(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(MemberDecl); if (MemberDecl->isEmpty()) { // If the class decl is empty, get its size. @@ -196,8 +192,8 @@ EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD, EmptyClassOffsetsMapTy::const_iterator I = EmptyClassOffsets.find(Offset); if (I == EmptyClassOffsets.end()) return true; - - const ClassVectorTy& Classes = I->second; + + const ClassVectorTy &Classes = I->second; if (std::find(Classes.begin(), Classes.end(), RD) == Classes.end()) return true; @@ -213,7 +209,7 @@ void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD, // If we have empty structures inside a union, we can assign both // the same offset. Just avoid pushing them twice in the list. - ClassVectorTy& Classes = EmptyClassOffsets[Offset]; + ClassVectorTy &Classes = EmptyClassOffsets[Offset]; if (std::find(Classes.begin(), Classes.end(), RD) != Classes.end()) return; @@ -237,8 +233,7 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info, // Traverse all non-virtual bases. const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class); - for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) { - BaseSubobjectInfo* Base = Info->Bases[I]; + for (const BaseSubobjectInfo *Base : Info->Bases) { if (Base->IsVirtual) continue; @@ -263,12 +258,12 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info, E = Info->Class->field_end(); I != E; ++I, ++FieldNo) { if (I->isBitField()) continue; - + CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo); if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset)) return false; } - + return true; } @@ -288,8 +283,7 @@ void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info, // Traverse all non-virtual bases. const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class); - for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) { - BaseSubobjectInfo* Base = Info->Bases[I]; + for (const BaseSubobjectInfo *Base : Info->Bases) { if (Base->IsVirtual) continue; @@ -348,13 +342,11 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD, const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); // Traverse all non-virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - if (I->isVirtual()) + for (const CXXBaseSpecifier &Base : RD->bases()) { + if (Base.isVirtual()) continue; - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl); if (!CanPlaceFieldSubobjectAtOffset(BaseDecl, Class, BaseOffset)) @@ -363,11 +355,9 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD, if (RD == Class) { // This is the most derived class, traverse virtual bases as well. - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { - const CXXRecordDecl *VBaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - + for (const CXXBaseSpecifier &Base : RD->vbases()) { + const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl(); + CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl); if (!CanPlaceFieldSubobjectAtOffset(VBaseDecl, Class, VBaseOffset)) return false; @@ -399,10 +389,8 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD, return true; QualType T = FD->getType(); - if (const RecordType *RT = T->getAs<RecordType>()) { - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return CanPlaceFieldSubobjectAtOffset(RD, RD, Offset); - } // If we have an array type we need to look at every element. if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) { @@ -410,8 +398,8 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD, const RecordType *RT = ElemTy->getAs<RecordType>(); if (!RT) return true; - - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + + const CXXRecordDecl *RD = RT->getAsCXXRecordDecl(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); uint64_t NumElements = Context.getConstantArrayElementCount(AT); @@ -460,13 +448,11 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD, const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); // Traverse all non-virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - if (I->isVirtual()) + for (const CXXBaseSpecifier &Base : RD->bases()) { + if (Base.isVirtual()) continue; - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(BaseDecl); UpdateEmptyFieldSubobjects(BaseDecl, Class, BaseOffset); @@ -474,11 +460,9 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD, if (RD == Class) { // This is the most derived class, traverse virtual bases as well. - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { - const CXXRecordDecl *VBaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - + for (const CXXBaseSpecifier &Base : RD->vbases()) { + const CXXRecordDecl *VBaseDecl = Base.getType()->getAsCXXRecordDecl(); + CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBaseDecl); UpdateEmptyFieldSubobjects(VBaseDecl, Class, VBaseOffset); } @@ -500,8 +484,7 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD, void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD, CharUnits Offset) { QualType T = FD->getType(); - if (const RecordType *RT = T->getAs<RecordType>()) { - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) { UpdateEmptyFieldSubobjects(RD, RD, Offset); return; } @@ -512,8 +495,8 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD, const RecordType *RT = ElemTy->getAs<RecordType>(); if (!RT) return; - - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + + const CXXRecordDecl *RD = RT->getAsCXXRecordDecl(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); uint64_t NumElements = Context.getConstantArrayElementCount(AT); @@ -649,9 +632,9 @@ protected: MaxFieldAlignment(CharUnits::Zero()), DataSize(0), NonVirtualSize(CharUnits::Zero()), NonVirtualAlignment(CharUnits::One()), - PrimaryBase(0), PrimaryBaseIsVirtual(false), + PrimaryBase(nullptr), PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), - FirstNearlyEmptyVBase(0) { } + FirstNearlyEmptyVBase(nullptr) {} /// Reset this RecordLayoutBuilder to a fresh state, using the given /// alignment as the initial alignment. This is used for the @@ -783,16 +766,14 @@ protected: void RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) { - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && + for (const auto &I : RD->bases()) { + assert(!I.getType()->isDependentType() && "Cannot layout class with dependent bases."); - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl(); // Check if this is a nearly empty virtual base. - if (I->isVirtual() && Context.isNearlyEmpty(Base)) { + if (I.isVirtual() && Context.isNearlyEmpty(Base)) { // If it's not an indirect primary base, then we've found our primary // base. if (!IndirectPrimaryBases.count(Base)) { @@ -825,14 +806,12 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { // If the record has a dynamic base class, attempt to choose a primary base // class. It is the first (in direct base class order) non-virtual dynamic // base class, if one exists. - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { + for (const auto &I : RD->bases()) { // Ignore virtual bases. - if (i->isVirtual()) + if (I.isVirtual()) continue; - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + const CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl(); if (Base->isDynamicClass()) { // We found it. @@ -885,11 +864,11 @@ RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD, Info->Class = RD; Info->IsVirtual = IsVirtual; - Info->Derived = 0; - Info->PrimaryVirtualBaseInfo = 0; - - const CXXRecordDecl *PrimaryVirtualBase = 0; - BaseSubobjectInfo *PrimaryVirtualBaseInfo = 0; + Info->Derived = nullptr; + Info->PrimaryVirtualBaseInfo = nullptr; + + const CXXRecordDecl *PrimaryVirtualBase = nullptr; + BaseSubobjectInfo *PrimaryVirtualBaseInfo = nullptr; // Check if this base has a primary virtual base. if (RD->getNumVBases()) { @@ -906,8 +885,8 @@ RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD, if (PrimaryVirtualBaseInfo->Derived) { // We did have info about this primary base, and it turns out that it // has already been claimed as a primary virtual base for another - // base. - PrimaryVirtualBase = 0; + // base. + PrimaryVirtualBase = nullptr; } else { // We can claim this base as our primary base. Info->PrimaryVirtualBaseInfo = PrimaryVirtualBaseInfo; @@ -918,13 +897,11 @@ RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD, } // Now go through all direct bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - bool IsVirtual = I->isVirtual(); - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - + for (const auto &I : RD->bases()) { + bool IsVirtual = I.isVirtual(); + + const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl(); + Info->Bases.push_back(ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, Info)); } @@ -944,15 +921,14 @@ RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD, } void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) { - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - bool IsVirtual = I->isVirtual(); + for (const auto &I : RD->bases()) { + bool IsVirtual = I.isVirtual(); + + const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl(); - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - // Compute the base subobject info for this base. - BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, 0); + BaseSubobjectInfo *Info = ComputeBaseSubobjectInfo(BaseDecl, IsVirtual, + nullptr); if (IsVirtual) { // ComputeBaseInfo has already added this base for us. @@ -999,8 +975,8 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { // If the primary virtual base was a primary virtual base of some other // base class we'll have to steal it. BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase); - PrimaryBaseInfo->Derived = 0; - + PrimaryBaseInfo->Derived = nullptr; + // We have a virtual primary base, insert it as an indirect primary base. IndirectPrimaryBases.insert(PrimaryBase); @@ -1033,15 +1009,13 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { } // Now lay out the non-virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { + for (const auto &I : RD->bases()) { // Ignore virtual bases. - if (I->isVirtual()) + if (I.isVirtual()) continue; - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl()); + const CXXRecordDecl *BaseDecl = I.getType()->getAsCXXRecordDecl(); // Skip the primary base, because we've already laid it out. The // !PrimaryBaseIsVirtual check is required because we might have a @@ -1093,8 +1067,7 @@ RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info, // Now go through all direct non-virtual bases. const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class); - for (unsigned I = 0, E = Info->Bases.size(); I != E; ++I) { - const BaseSubobjectInfo *Base = Info->Bases[I]; + for (const BaseSubobjectInfo *Base : Info->Bases) { if (Base->IsVirtual) continue; @@ -1118,15 +1091,13 @@ RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual(); } - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && + for (const CXXBaseSpecifier &Base : RD->bases()) { + assert(!Base.getType()->isDependentType() && "Cannot layout class with dependent bases."); - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl()); + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); - if (I->isVirtual()) { + if (Base.isVirtual()) { if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) { bool IndirectPrimaryBase = IndirectPrimaryBases.count(BaseDecl); @@ -1191,7 +1162,7 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { } } - CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlign(); + CharUnits UnpackedBaseAlign = Layout.getNonVirtualAlignment(); CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign; // If we have an empty base class, try to place it at offset 0. @@ -1326,22 +1297,18 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { #ifndef NDEBUG // Check that we have base offsets for all bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - if (I->isVirtual()) + for (const CXXBaseSpecifier &Base : RD->bases()) { + if (Base.isVirtual()) continue; - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); assert(Bases.count(BaseDecl) && "Did not find base offset!"); } // And all virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + for (const CXXBaseSpecifier &Base : RD->vbases()) { + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); assert(VBases.count(BaseDecl) && "Did not find base offset!"); } @@ -1374,9 +1341,8 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Layout each field, for now, just sequentially, respecting alignment. In // the future, this will need to be tweakable by targets. - for (RecordDecl::field_iterator Field = D->field_begin(), - FieldEnd = D->field_end(); Field != FieldEnd; ++Field) - LayoutField(*Field); + for (const auto *Field : D->fields()) + LayoutField(Field); } void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, @@ -1396,14 +1362,13 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, }; QualType Type; - for (unsigned I = 0, E = llvm::array_lengthof(IntegralPODTypes); - I != E; ++I) { - uint64_t Size = Context.getTypeSize(IntegralPODTypes[I]); + for (const QualType &QT : IntegralPODTypes) { + uint64_t Size = Context.getTypeSize(QT); if (Size > FieldSize) break; - Type = IntegralPODTypes[I]; + Type = QT; } assert(!Type.isNull() && "Did not find a type!"); @@ -1452,127 +1417,224 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { uint64_t TypeSize = FieldInfo.first; unsigned FieldAlign = FieldInfo.second; + // UnfilledBitsInLastUnit is the difference between the end of the + // last allocated bitfield (i.e. the first bit offset available for + // bitfields) and the end of the current data size in bits (i.e. the + // first bit offset available for non-bitfields). The current data + // size in bits is always a multiple of the char size; additionally, + // for ms_struct records it's also a multiple of the + // LastBitfieldTypeSize (if set). + + // The struct-layout algorithm is dictated by the platform ABI, + // which in principle could use almost any rules it likes. In + // practice, UNIXy targets tend to inherit the algorithm described + // in the System V generic ABI. The basic bitfield layout rule in + // System V is to place bitfields at the next available bit offset + // where the entire bitfield would fit in an aligned storage unit of + // the declared type; it's okay if an earlier or later non-bitfield + // is allocated in the same storage unit. However, some targets + // (those that !useBitFieldTypeAlignment(), e.g. ARM APCS) don't + // require this storage unit to be aligned, and therefore always put + // the bitfield at the next available bit offset. + + // ms_struct basically requests a complete replacement of the + // platform ABI's struct-layout algorithm, with the high-level goal + // of duplicating MSVC's layout. For non-bitfields, this follows + // the the standard algorithm. The basic bitfield layout rule is to + // allocate an entire unit of the bitfield's declared type + // (e.g. 'unsigned long'), then parcel it up among successive + // bitfields whose declared types have the same size, making a new + // unit as soon as the last can no longer store the whole value. + // Since it completely replaces the platform ABI's algorithm, + // settings like !useBitFieldTypeAlignment() do not apply. + + // A zero-width bitfield forces the use of a new storage unit for + // later bitfields. In general, this occurs by rounding up the + // current size of the struct as if the algorithm were about to + // place a non-bitfield of the field's formal type. Usually this + // does not change the alignment of the struct itself, but it does + // on some targets (those that useZeroLengthBitfieldAlignment(), + // e.g. ARM). In ms_struct layout, zero-width bitfields are + // ignored unless they follow a non-zero-width bitfield. + + // A field alignment restriction (e.g. from #pragma pack) or + // specification (e.g. from __attribute__((aligned))) changes the + // formal alignment of the field. For System V, this alters the + // required alignment of the notional storage unit that must contain + // the bitfield. For ms_struct, this only affects the placement of + // new storage units. In both cases, the effect of #pragma pack is + // ignored on zero-width bitfields. + + // On System V, a packed field (e.g. from #pragma pack or + // __attribute__((packed))) always uses the next available bit + // offset. + + // In an ms_struct struct, the alignment of a fundamental type is + // always equal to its size. This is necessary in order to mimic + // the i386 alignment rules on targets which might not fully align + // all types (e.g. Darwin PPC32, where alignof(long long) == 4). + + // First, some simple bookkeeping to perform for ms_struct structs. if (IsMsStruct) { - // The field alignment for integer types in ms_struct structs is - // always the size. + // The field alignment for integer types is always the size. FieldAlign = TypeSize; - // Ignore zero-length bitfields after non-bitfields in ms_struct structs. - if (!FieldSize && !LastBitfieldTypeSize) - FieldAlign = 1; - // If a bitfield is followed by a bitfield of a different size, don't - // pack the bits together in ms_struct structs. + + // If the previous field was not a bitfield, or was a bitfield + // with a different storage unit size, we're done with that + // storage unit. if (LastBitfieldTypeSize != TypeSize) { + // Also, ignore zero-length bitfields after non-bitfields. + if (!LastBitfieldTypeSize && !FieldSize) + FieldAlign = 1; + UnfilledBitsInLastUnit = 0; LastBitfieldTypeSize = 0; } } - uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit; - uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset; - - bool ZeroLengthBitfield = false; - if (!Context.getTargetInfo().useBitFieldTypeAlignment() && - Context.getTargetInfo().useZeroLengthBitfieldAlignment() && - FieldSize == 0) { - // The alignment of a zero-length bitfield affects the alignment - // of the next member. The alignment is the max of the zero - // length bitfield's alignment and a target specific fixed value. - ZeroLengthBitfield = true; - unsigned ZeroLengthBitfieldBoundary = - Context.getTargetInfo().getZeroLengthBitfieldBoundary(); - if (ZeroLengthBitfieldBoundary > FieldAlign) - FieldAlign = ZeroLengthBitfieldBoundary; - } - + // If the field is wider than its declared type, it follows + // different rules in all cases. if (FieldSize > TypeSize) { LayoutWideBitField(FieldSize, TypeSize, FieldPacked, D); return; } - // The align if the field is not packed. This is to check if the attribute - // was unnecessary (-Wpacked). + // Compute the next available bit offset. + uint64_t FieldOffset = + IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit); + + // Handle targets that don't honor bitfield type alignment. + if (!IsMsStruct && !Context.getTargetInfo().useBitFieldTypeAlignment()) { + // Some such targets do honor it on zero-width bitfields. + if (FieldSize == 0 && + Context.getTargetInfo().useZeroLengthBitfieldAlignment()) { + // The alignment to round up to is the max of the field's natural + // alignment and a target-specific fixed value (sometimes zero). + unsigned ZeroLengthBitfieldBoundary = + Context.getTargetInfo().getZeroLengthBitfieldBoundary(); + FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary); + + // If that doesn't apply, just ignore the field alignment. + } else { + FieldAlign = 1; + } + } + + // Remember the alignment we would have used if the field were not packed. unsigned UnpackedFieldAlign = FieldAlign; - uint64_t UnpackedFieldOffset = FieldOffset; - if (!Context.getTargetInfo().useBitFieldTypeAlignment() && !ZeroLengthBitfield) - UnpackedFieldAlign = 1; - if (FieldPacked || - (!Context.getTargetInfo().useBitFieldTypeAlignment() && !ZeroLengthBitfield)) + // Ignore the field alignment if the field is packed unless it has zero-size. + if (!IsMsStruct && FieldPacked && FieldSize != 0) FieldAlign = 1; - FieldAlign = std::max(FieldAlign, D->getMaxAlignment()); - UnpackedFieldAlign = std::max(UnpackedFieldAlign, D->getMaxAlignment()); - // The maximum field alignment overrides the aligned attribute. - if (!MaxFieldAlignment.isZero() && FieldSize != 0) { + // But, if there's an 'aligned' attribute on the field, honor that. + if (unsigned ExplicitFieldAlign = D->getMaxAlignment()) { + FieldAlign = std::max(FieldAlign, ExplicitFieldAlign); + UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign); + } + + // But, if there's a #pragma pack in play, that takes precedent over + // even the 'aligned' attribute, for non-zero-width bitfields. + if (!MaxFieldAlignment.isZero() && FieldSize) { unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment); FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits); } - // ms_struct bitfields always have to start at a round alignment. - if (IsMsStruct && !LastBitfieldTypeSize) { - FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); - UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, - UnpackedFieldAlign); - } + // For purposes of diagnostics, we're going to simultaneously + // compute the field offsets that we would have used if we weren't + // adding any alignment padding or if the field weren't packed. + uint64_t UnpaddedFieldOffset = FieldOffset; + uint64_t UnpackedFieldOffset = FieldOffset; - // Check if we need to add padding to give the field the correct alignment. - if (FieldSize == 0 || - (MaxFieldAlignment.isZero() && - (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) - FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); + // Check if we need to add padding to fit the bitfield within an + // allocation unit with the right size and alignment. The rules are + // somewhat different here for ms_struct structs. + if (IsMsStruct) { + // If it's not a zero-width bitfield, and we can fit the bitfield + // into the active storage unit (and we haven't already decided to + // start a new storage unit), just do so, regardless of any other + // other consideration. Otherwise, round up to the right alignment. + if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) { + FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); + UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, + UnpackedFieldAlign); + UnfilledBitsInLastUnit = 0; + } - if (FieldSize == 0 || - (MaxFieldAlignment.isZero() && - (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) - UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, - UnpackedFieldAlign); + } else { + // #pragma pack, with any value, suppresses the insertion of padding. + bool AllowPadding = MaxFieldAlignment.isZero(); + + // Compute the real offset. + if (FieldSize == 0 || + (AllowPadding && + (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) { + FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); + } - // Padding members don't affect overall alignment, unless zero length bitfield - // alignment is enabled. - if (!D->getIdentifier() && - !Context.getTargetInfo().useZeroLengthBitfieldAlignment() && - !IsMsStruct) - FieldAlign = UnpackedFieldAlign = 1; + // Repeat the computation for diagnostic purposes. + if (FieldSize == 0 || + (AllowPadding && + (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) + UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, + UnpackedFieldAlign); + } + // If we're using external layout, give the external layout a chance + // to override this information. if (ExternalLayout) FieldOffset = updateExternalFieldOffset(D, FieldOffset); - // Place this field at the current location. + // Okay, place the bitfield at the calculated offset. FieldOffsets.push_back(FieldOffset); + // Bookkeeping: + + // Anonymous members don't affect the overall record alignment, + // except on targets where they do. + if (!IsMsStruct && + !Context.getTargetInfo().useZeroLengthBitfieldAlignment() && + !D->getIdentifier()) + FieldAlign = UnpackedFieldAlign = 1; + + // Diagnose differences in layout due to padding or packing. if (!ExternalLayout) CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset, UnpackedFieldAlign, FieldPacked, D); // Update DataSize to include the last byte containing (part of) the bitfield. + + // For unions, this is just a max operation, as usual. if (IsUnion) { // FIXME: I think FieldSize should be TypeSize here. setDataSize(std::max(getDataSizeInBits(), FieldSize)); - } else { - if (IsMsStruct && FieldSize) { - // Under ms_struct, a bitfield always takes up space equal to the size - // of the type. We can't just change the alignment computation on the - // other codepath because of the way this interacts with #pragma pack: - // in a packed struct, we need to allocate misaligned space in the - // struct to hold the bitfield. - if (!UnfilledBitsInLastUnit) { - setDataSize(FieldOffset + TypeSize); - UnfilledBitsInLastUnit = TypeSize - FieldSize; - } else if (UnfilledBitsInLastUnit < FieldSize) { - setDataSize(getDataSizeInBits() + TypeSize); - UnfilledBitsInLastUnit = TypeSize - FieldSize; - } else { - UnfilledBitsInLastUnit -= FieldSize; - } - LastBitfieldTypeSize = TypeSize; - } else { - uint64_t NewSizeInBits = FieldOffset + FieldSize; - uint64_t BitfieldAlignment = Context.getTargetInfo().getCharAlign(); - setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, BitfieldAlignment)); - UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits; - LastBitfieldTypeSize = 0; + + // For non-zero-width bitfields in ms_struct structs, allocate a new + // storage unit if necessary. + } else if (IsMsStruct && FieldSize) { + // We should have cleared UnfilledBitsInLastUnit in every case + // where we changed storage units. + if (!UnfilledBitsInLastUnit) { + setDataSize(FieldOffset + TypeSize); + UnfilledBitsInLastUnit = TypeSize; } + UnfilledBitsInLastUnit -= FieldSize; + LastBitfieldTypeSize = TypeSize; + + // Otherwise, bump the data size up to include the bitfield, + // including padding up to char alignment, and then remember how + // bits we didn't use. + } else { + uint64_t NewSizeInBits = FieldOffset + FieldSize; + uint64_t CharAlignment = Context.getTargetInfo().getCharAlign(); + setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, CharAlignment)); + UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits; + + // The only time we can get here for an ms_struct is if this is a + // zero-width bitfield, which doesn't count as anything for the + // purposes of unfilled bits. + LastBitfieldTypeSize = 0; } // Update the size. @@ -1870,28 +1932,26 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, const CXXRecordDecl *RD) { // If a class isn't polymorphic it doesn't have a key function. if (!RD->isPolymorphic()) - return 0; + return nullptr; // A class that is not externally visible doesn't have a key function. (Or // at least, there's no point to assigning a key function to such a class; // this doesn't affect the ABI.) if (!RD->isExternallyVisible()) - return 0; + return nullptr; - // Template instantiations don't have key functions,see Itanium C++ ABI 5.2.6. + // Template instantiations don't have key functions per Itanium C++ ABI 5.2.6. // Same behavior as GCC. TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind(); if (TSK == TSK_ImplicitInstantiation || + TSK == TSK_ExplicitInstantiationDeclaration || TSK == TSK_ExplicitInstantiationDefinition) - return 0; + return nullptr; bool allowInlineFunctions = Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline(); - for (CXXRecordDecl::method_iterator I = RD->method_begin(), - E = RD->method_end(); I != E; ++I) { - const CXXMethodDecl *MD = *I; - + for (const CXXMethodDecl *MD : RD->methods()) { if (!MD->isVirtual()) continue; @@ -1924,7 +1984,7 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, return MD; } - return 0; + return nullptr; } DiagnosticBuilder @@ -1979,50 +2039,101 @@ static bool isMsLayout(const RecordDecl* D) { } // This section contains an implementation of struct layout that is, up to the -// included tests, compatible with cl.exe (2012). The layout produced is +// included tests, compatible with cl.exe (2013). The layout produced is // significantly different than those produced by the Itanium ABI. Here we note // the most important differences. // // * The alignment of bitfields in unions is ignored when computing the // alignment of the union. -// * The existance of zero-width bitfield that occurs after anything other than +// * The existence of zero-width bitfield that occurs after anything other than // a non-zero length bitfield is ignored. +// * There is no explicit primary base for the purposes of layout. All bases +// with vfptrs are laid out first, followed by all bases without vfptrs. // * The Itanium equivalent vtable pointers are split into a vfptr (virtual // function pointer) and a vbptr (virtual base pointer). They can each be // shared with a, non-virtual bases. These bases need not be the same. vfptrs -// always occur at offset 0. vbptrs can occur at an -// arbitrary offset and are placed after non-virtual bases but before fields. +// always occur at offset 0. vbptrs can occur at an arbitrary offset and are +// placed after the lexiographically last non-virtual base. This placement +// is always before fields but can be in the middle of the non-virtual bases +// due to the two-pass layout scheme for non-virtual-bases. // * Virtual bases sometimes require a 'vtordisp' field that is laid out before // the virtual base and is used in conjunction with virtual overrides during -// construction and destruction. -// * vfptrs are allocated in a block of memory equal to the alignment of the -// fields and non-virtual bases at offset 0 in 32 bit mode and in a pointer -// sized block of memory in 64 bit mode. -// * vbptrs are allocated in a block of memory equal to the alignment of the -// fields and non-virtual bases. This block is at a potentially unaligned -// offset. If the allocation slot is unaligned and the alignment is less than -// or equal to the pointer size, additional space is allocated so that the -// pointer can be aligned properly. This causes very strange effects on the -// placement of objects after the allocated block. (see the code). +// construction and destruction. This is always a 4 byte value and is used as +// an alternative to constructor vtables. // * vtordisps are allocated in a block of memory with size and alignment equal // to the alignment of the completed structure (before applying __declspec( // align())). The vtordisp always occur at the end of the allocation block, // immediately prior to the virtual base. -// * The last zero sized non-virtual base is allocated after the placement of -// vbptr if one exists and can be placed at the end of the struct, potentially -// aliasing either the first member or another struct allocated after this -// one. -// * The last zero size virtual base may be placed at the end of the struct. -// and can potentially alias a zero sized type in the next struct. -// * If the last field is a non-zero length bitfield and we have any virtual -// bases then some extra padding is added before the virtual bases for no -// obvious reason. -// * When laying out empty non-virtual bases, an extra byte of padding is added -// if the non-virtual base before the empty non-virtual base has a vbptr. - +// * vfptrs are injected after all bases and fields have been laid out. In +// order to guarantee proper alignment of all fields, the vfptr injection +// pushes all bases and fields back by the alignment imposed by those bases +// and fields. This can potentially add a significant amount of padding. +// vfptrs are always injected at offset 0. +// * vbptrs are injected after all bases and fields have been laid out. In +// order to guarantee proper alignment of all fields, the vfptr injection +// pushes all bases and fields back by the alignment imposed by those bases +// and fields. This can potentially add a significant amount of padding. +// vbptrs are injected immediately after the last non-virtual base as +// lexiographically ordered in the code. If this site isn't pointer aligned +// the vbptr is placed at the next properly aligned location. Enough padding +// is added to guarantee a fit. +// * The last zero sized non-virtual base can be placed at the end of the +// struct (potentially aliasing another object), or may alias with the first +// field, even if they are of the same type. +// * The last zero size virtual base may be placed at the end of the struct +// potentially aliasing another object. +// * The ABI attempts to avoid aliasing of zero sized bases by adding padding +// between bases or vbases with specific properties. The criteria for +// additional padding between two bases is that the first base is zero sized +// or ends with a zero sized subobject and the second base is zero sized or +// trails with a zero sized base or field (sharing of vfptrs can reorder the +// layout of the so the leading base is not always the first one declared). +// This rule does take into account fields that are not records, so padding +// will occur even if the last field is, e.g. an int. The padding added for +// bases is 1 byte. The padding added between vbases depends on the alignment +// of the object but is at least 4 bytes (in both 32 and 64 bit modes). +// * There is no concept of non-virtual alignment, non-virtual alignment and +// alignment are always identical. +// * There is a distinction between alignment and required alignment. +// __declspec(align) changes the required alignment of a struct. This +// alignment is _always_ obeyed, even in the presence of #pragma pack. A +// record inherites required alignment from all of its fields an bases. +// * __declspec(align) on bitfields has the effect of changing the bitfield's +// alignment instead of its required alignment. This is the only known way +// to make the alignment of a struct bigger than 8. Interestingly enough +// this alignment is also immune to the effects of #pragma pack and can be +// used to create structures with large alignment under #pragma pack. +// However, because it does not impact required alignment, such a structure, +// when used as a field or base, will not be aligned if #pragma pack is +// still active at the time of use. +// +// Known incompatibilities: +// * all: #pragma pack between fields in a record +// * 2010 and back: If the last field in a record is a bitfield, every object +// laid out after the record will have extra padding inserted before it. The +// extra padding will have size equal to the size of the storage class of the +// bitfield. 0 sized bitfields don't exhibit this behavior and the extra +// padding can be avoided by adding a 0 sized bitfield after the non-zero- +// sized bitfield. +// * 2012 and back: In 64-bit mode, if the alignment of a record is 16 or +// greater due to __declspec(align()) then a second layout phase occurs after +// The locations of the vf and vb pointers are known. This layout phase +// suffers from the "last field is a bitfield" bug in 2010 and results in +// _every_ field getting padding put in front of it, potentially including the +// vfptr, leaving the vfprt at a non-zero location which results in a fault if +// anything tries to read the vftbl. The second layout phase also treats +// bitfields as separate entities and gives them each storage rather than +// packing them. Additionally, because this phase appears to perform a +// (an unstable) sort on the members before laying them out and because merged +// bitfields have the same address, the bitfields end up in whatever order +// the sort left them in, a behavior we could never hope to replicate. namespace { struct MicrosoftRecordLayoutBuilder { + struct ElementInfo { + CharUnits Size; + CharUnits Alignment; + }; typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; MicrosoftRecordLayoutBuilder(const ASTContext &Context) : Context(Context) {} private: @@ -2030,19 +2141,20 @@ private: LLVM_DELETED_FUNCTION; void operator=(const MicrosoftRecordLayoutBuilder &) LLVM_DELETED_FUNCTION; public: - void layout(const RecordDecl *RD); void cxxLayout(const CXXRecordDecl *RD); /// \brief Initializes size and alignment and honors some flags. void initializeLayout(const RecordDecl *RD); /// \brief Initialized C++ layout, compute alignment and virtual alignment and - /// existance of vfptrs and vbptrs. Alignment is needed before the vfptr is + /// existence of vfptrs and vbptrs. Alignment is needed before the vfptr is /// laid out. void initializeCXXLayout(const CXXRecordDecl *RD); - void layoutVFPtr(const CXXRecordDecl *RD); void layoutNonVirtualBases(const CXXRecordDecl *RD); - void layoutNonVirtualBase(const CXXRecordDecl *RD); - void layoutVBPtr(const CXXRecordDecl *RD); + void layoutNonVirtualBase(const CXXRecordDecl *BaseDecl, + const ASTRecordLayout &BaseLayout, + const ASTRecordLayout *&PreviousBaseLayout); + void injectVFPtr(const CXXRecordDecl *RD); + void injectVBPtr(const CXXRecordDecl *RD); /// \brief Lays out the fields of the record. Also rounds size up to /// alignment. void layoutFields(const RecordDecl *RD); @@ -2052,22 +2164,14 @@ public: /// special cases associated with zero-width bit-fields. void layoutZeroWidthBitField(const FieldDecl *FD); void layoutVirtualBases(const CXXRecordDecl *RD); - void layoutVirtualBase(const CXXRecordDecl *RD, bool HasVtordisp); - /// \brief Flushes the lazy virtual base and conditionally rounds up to - /// alignment. - void finalizeCXXLayout(const CXXRecordDecl *RD); - void honorDeclspecAlign(const RecordDecl *RD); - - /// \brief Updates the alignment of the type. This function doesn't take any - /// properties (such as packedness) into account. getAdjustedFieldInfo() - /// adjustes for packedness. - void updateAlignment(CharUnits NewAlignment) { - Alignment = std::max(Alignment, NewAlignment); - } - /// \brief Gets the size and alignment taking attributes into account. - std::pair<CharUnits, CharUnits> getAdjustedFieldInfo(const FieldDecl *FD); - /// \brief Places a field at offset 0. - void placeFieldAtZero() { FieldOffsets.push_back(0); } + void finalizeLayout(const RecordDecl *RD); + /// \brief Gets the size and alignment of a base taking pragma pack and + /// __declspec(align) into account. + ElementInfo getAdjustedElementInfo(const ASTRecordLayout &Layout); + /// \brief Gets the size and alignment of a field taking pragma pack and + /// __declspec(align) into account. It also updates RequiredAlignment as a + /// side effect because it is most convenient to do so here. + ElementInfo getAdjustedElementInfo(const FieldDecl *FD); /// \brief Places a field at an offset in CharUnits. void placeFieldAtOffset(CharUnits FieldOffset) { FieldOffsets.push_back(Context.toBits(FieldOffset)); @@ -2079,334 +2183,280 @@ public: /// \brief Compute the set of virtual bases for which vtordisps are required. llvm::SmallPtrSet<const CXXRecordDecl *, 2> computeVtorDispSet(const CXXRecordDecl *RD); - const ASTContext &Context; /// \brief The size of the record being laid out. CharUnits Size; + /// \brief The non-virtual size of the record layout. + CharUnits NonVirtualSize; + /// \brief The data size of the record layout. + CharUnits DataSize; /// \brief The current alignment of the record layout. CharUnits Alignment; - /// \brief The collection of field offsets. - SmallVector<uint64_t, 16> FieldOffsets; /// \brief The maximum allowed field alignment. This is set by #pragma pack. CharUnits MaxFieldAlignment; - /// \brief Alignment does not occur for virtual bases unless something - /// forces it to by explicitly using __declspec(align()) - bool AlignAfterVBases : 1; - bool IsUnion : 1; - /// \brief True if the last field laid out was a bitfield and was not 0 - /// width. - bool LastFieldIsNonZeroWidthBitfield : 1; + /// \brief The alignment that this record must obey. This is imposed by + /// __declspec(align()) on the record itself or one of its fields or bases. + CharUnits RequiredAlignment; /// \brief The size of the allocation of the currently active bitfield. /// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield /// is true. CharUnits CurrentBitfieldSize; - /// \brief The number of remaining bits in our last bitfield allocation. - /// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield is - /// true. - unsigned RemainingBitsInField; - - /// \brief The data alignment of the record layout. - CharUnits DataSize; - /// \brief The alignment of the non-virtual portion of the record layout - /// without the impact of the virtual pointers. - /// Only used for C++ layouts. - CharUnits BasesAndFieldsAlignment; - /// \brief The alignment of the non-virtual portion of the record layout - /// Only used for C++ layouts. - CharUnits NonVirtualAlignment; - /// \brief The additional alignment imposed by the virtual bases. - CharUnits VirtualAlignment; + /// \brief Offset to the virtual base table pointer (if one exists). + CharUnits VBPtrOffset; + /// \brief The size and alignment info of a pointer. + ElementInfo PointerInfo; /// \brief The primary base class (if one exists). const CXXRecordDecl *PrimaryBase; /// \brief The class we share our vb-pointer with. const CXXRecordDecl *SharedVBPtrBase; - /// \brief True if the class has a vftable pointer that can be extended - /// by this class or classes derived from it. Such a vfptr will always occur - /// at offset 0. - bool HasExtendableVFPtr : 1; - /// \brief True if the class has a (not necessarily its own) vbtable pointer. - bool HasVBPtr : 1; - /// \brief Offset to the virtual base table pointer (if one exists). - CharUnits VBPtrOffset; + /// \brief The collection of field offsets. + SmallVector<uint64_t, 16> FieldOffsets; /// \brief Base classes and their offsets in the record. BaseOffsetsMapTy Bases; /// \brief virtual base classes and their offsets in the record. ASTRecordLayout::VBaseOffsetsMapTy VBases; - /// \brief The size of a pointer. - CharUnits PointerSize; - /// \brief The alignment of a pointer. - CharUnits PointerAlignment; - /// \brief Holds an empty base we haven't yet laid out. - const CXXRecordDecl *LazyEmptyBase; - /// \brief Lets us know if the last base we laid out was empty. Only used - /// when adjusting the placement of a last zero-sized base in 64 bit mode. - bool LastBaseWasEmpty; - /// \brief Lets us know if we're in 64-bit mode - bool Is64BitMode; - /// \brief True if the last non-virtual base has a vbptr. - bool LastNonVirtualBaseHasVBPtr; + /// \brief The number of remaining bits in our last bitfield allocation. + /// This value isn't meaningful unless LastFieldIsNonZeroWidthBitfield is + /// true. + unsigned RemainingBitsInField; + bool IsUnion : 1; + /// \brief True if the last field laid out was a bitfield and was not 0 + /// width. + bool LastFieldIsNonZeroWidthBitfield : 1; + /// \brief True if the class has its own vftable pointer. + bool HasOwnVFPtr : 1; + /// \brief True if the class has a vbtable pointer. + bool HasVBPtr : 1; + /// \brief True if the last sub-object within the type is zero sized or the + /// object itself is zero sized. This *does not* count members that are not + /// records. Only used for MS-ABI. + bool EndsWithZeroSizedObject : 1; + /// \brief True if this class is zero sized or first base is zero sized or + /// has this property. Only used for MS-ABI. + bool LeadsWithZeroSizedBase : 1; }; } // namespace -std::pair<CharUnits, CharUnits> -MicrosoftRecordLayoutBuilder::getAdjustedFieldInfo(const FieldDecl *FD) { - std::pair<CharUnits, CharUnits> FieldInfo = - Context.getTypeInfoInChars(FD->getType()); +MicrosoftRecordLayoutBuilder::ElementInfo +MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( + const ASTRecordLayout &Layout) { + ElementInfo Info; + Info.Alignment = Layout.getAlignment(); + // Respect pragma pack. + if (!MaxFieldAlignment.isZero()) + Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment); + // Track zero-sized subobjects here where it's already available. + EndsWithZeroSizedObject = Layout.hasZeroSizedSubObject(); + // Respect required alignment, this is necessary because we may have adjusted + // the alignment in the case of pragam pack. Note that the required alignment + // doesn't actually apply to the struct alignment at this point. + Alignment = std::max(Alignment, Info.Alignment); + RequiredAlignment = std::max(RequiredAlignment, Layout.getRequiredAlignment()); + Info.Alignment = std::max(Info.Alignment, Layout.getRequiredAlignment()); + Info.Size = Layout.getNonVirtualSize(); + return Info; +} - // If we're not on win32 and using ms_struct the field alignment will be wrong - // for 64 bit types, so we fix that here. - if (FD->getASTContext().getTargetInfo().getTriple().getOS() != - llvm::Triple::Win32) { - QualType T = Context.getBaseElementType(FD->getType()); - if (const BuiltinType *BTy = T->getAs<BuiltinType>()) { - CharUnits TypeSize = Context.getTypeSizeInChars(BTy); - if (TypeSize > FieldInfo.second) - FieldInfo.second = TypeSize; +MicrosoftRecordLayoutBuilder::ElementInfo +MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( + const FieldDecl *FD) { + ElementInfo Info; + std::tie(Info.Size, Info.Alignment) = + Context.getTypeInfoInChars(FD->getType()); + // Respect align attributes. + CharUnits FieldRequiredAlignment = + Context.toCharUnitsFromBits(FD->getMaxAlignment()); + // Respect attributes applied to subobjects of the field. + if (FD->isBitField()) + // For some reason __declspec align impacts alignment rather than required + // alignment when it is applied to bitfields. + Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment); + else { + if (auto RT = + FD->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) { + auto const &Layout = Context.getASTRecordLayout(RT->getDecl()); + EndsWithZeroSizedObject = Layout.hasZeroSizedSubObject(); + FieldRequiredAlignment = std::max(FieldRequiredAlignment, + Layout.getRequiredAlignment()); } + // Capture required alignment as a side-effect. + RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment); } - - // Respect packed attribute. + // Respect pragma pack, attribute pack and declspec align + if (!MaxFieldAlignment.isZero()) + Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment); if (FD->hasAttr<PackedAttr>()) - FieldInfo.second = CharUnits::One(); - // Respect pack pragma. - else if (!MaxFieldAlignment.isZero()) - FieldInfo.second = std::min(FieldInfo.second, MaxFieldAlignment); - // Respect alignment attributes. - if (unsigned fieldAlign = FD->getMaxAlignment()) { - CharUnits FieldAlign = Context.toCharUnitsFromBits(fieldAlign); - AlignAfterVBases = true; - FieldInfo.second = std::max(FieldInfo.second, FieldAlign); - } - return FieldInfo; -} - -void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) { - IsUnion = RD->isUnion(); - Is64BitMode = Context.getTargetInfo().getPointerWidth(0) == 64; - - Size = CharUnits::Zero(); - Alignment = CharUnits::One(); - AlignAfterVBases = false; - - // Compute the maximum field alignment. - MaxFieldAlignment = CharUnits::Zero(); - // Honor the default struct packing maximum alignment flag. - if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) - MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment); - // Honor the packing attribute. - if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr<MaxFieldAlignmentAttr>()) - MaxFieldAlignment = Context.toCharUnitsFromBits(MFAA->getAlignment()); - // Packed attribute forces max field alignment to be 1. - if (RD->hasAttr<PackedAttr>()) - MaxFieldAlignment = CharUnits::One(); + Info.Alignment = CharUnits::One(); + Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment); + return Info; } void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) { initializeLayout(RD); layoutFields(RD); - honorDeclspecAlign(RD); + DataSize = Size = Size.RoundUpToAlignment(Alignment); + RequiredAlignment = std::max( + RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment())); + finalizeLayout(RD); } void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) { initializeLayout(RD); initializeCXXLayout(RD); - layoutVFPtr(RD); layoutNonVirtualBases(RD); - layoutVBPtr(RD); layoutFields(RD); - DataSize = Size; - NonVirtualAlignment = Alignment; + injectVBPtr(RD); + injectVFPtr(RD); + if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase)) + Alignment = std::max(Alignment, PointerInfo.Alignment); + auto RoundingAlignment = Alignment; + if (!MaxFieldAlignment.isZero()) + RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment); + NonVirtualSize = Size = Size.RoundUpToAlignment(RoundingAlignment); + RequiredAlignment = std::max( + RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment())); layoutVirtualBases(RD); - finalizeCXXLayout(RD); - honorDeclspecAlign(RD); + finalizeLayout(RD); +} + +void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) { + IsUnion = RD->isUnion(); + Size = CharUnits::Zero(); + Alignment = CharUnits::One(); + // In 64-bit mode we always perform an alignment step after laying out vbases. + // In 32-bit mode we do not. The check to see if we need to perform alignment + // checks the RequiredAlignment field and performs alignment if it isn't 0. + RequiredAlignment = Context.getTargetInfo().getPointerWidth(0) == 64 ? + CharUnits::One() : CharUnits::Zero(); + // Compute the maximum field alignment. + MaxFieldAlignment = CharUnits::Zero(); + // Honor the default struct packing maximum alignment flag. + if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) + MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment); + // Honor the packing attribute. The MS-ABI ignores pragma pack if its larger + // than the pointer size. + if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr<MaxFieldAlignmentAttr>()){ + unsigned PackedAlignment = MFAA->getAlignment(); + if (PackedAlignment <= Context.getTargetInfo().getPointerWidth(0)) + MaxFieldAlignment = Context.toCharUnitsFromBits(PackedAlignment); + } + // Packed attribute forces max field alignment to be 1. + if (RD->hasAttr<PackedAttr>()) + MaxFieldAlignment = CharUnits::One(); } void MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) { - // Calculate pointer size and alignment. - PointerSize = + EndsWithZeroSizedObject = false; + LeadsWithZeroSizedBase = false; + HasOwnVFPtr = false; + HasVBPtr = false; + PrimaryBase = nullptr; + SharedVBPtrBase = nullptr; + // Calculate pointer size and alignment. These are used for vfptr and vbprt + // injection. + PointerInfo.Size = Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); - PointerAlignment = PointerSize; + PointerInfo.Alignment = PointerInfo.Size; + // Respect pragma pack. if (!MaxFieldAlignment.isZero()) - PointerAlignment = std::min(PointerAlignment, MaxFieldAlignment); - - // Initialize information about the bases. - HasVBPtr = false; - HasExtendableVFPtr = false; - SharedVBPtrBase = 0; - PrimaryBase = 0; - VirtualAlignment = CharUnits::One(); - AlignAfterVBases = Is64BitMode; + PointerInfo.Alignment = std::min(PointerInfo.Alignment, MaxFieldAlignment); +} - // If the record has a dynamic base class, attempt to choose a primary base - // class. It is the first (in direct base class order) non-virtual dynamic - // base class, if one exists. - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); - i != e; ++i) { - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl); - // Handle forced alignment. - if (Layout.getAlignAfterVBases()) - AlignAfterVBases = true; - // Handle virtual bases. - if (i->isVirtual()) { - VirtualAlignment = std::max(VirtualAlignment, Layout.getAlignment()); +void +MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { + // The MS-ABI lays out all bases that contain leading vfptrs before it lays + // out any bases that do not contain vfptrs. We implement this as two passes + // over the bases. This approach guarantees that the primary base is laid out + // first. We use these passes to calculate some additional aggregated + // information about the bases, such as reqruied alignment and the presence of + // zero sized members. + const ASTRecordLayout *PreviousBaseLayout = nullptr; + // Iterate through the bases and lay out the non-virtual ones. + for (const CXXBaseSpecifier &Base : RD->bases()) { + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); + const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl); + // Mark and skip virtual bases. + if (Base.isVirtual()) { HasVBPtr = true; continue; } - // We located a primary base class! - if (!PrimaryBase && Layout.hasExtendableVFPtr()) { - PrimaryBase = BaseDecl; - HasExtendableVFPtr = true; - } - // We located a base to share a VBPtr with! - if (!SharedVBPtrBase && Layout.hasVBPtr()) { + // Check fo a base to share a VBPtr with. + if (!SharedVBPtrBase && BaseLayout.hasVBPtr()) { SharedVBPtrBase = BaseDecl; HasVBPtr = true; } - updateAlignment(Layout.getAlignment()); + // Only lay out bases with extendable VFPtrs on the first pass. + if (!BaseLayout.hasExtendableVFPtr()) + continue; + // If we don't have a primary base, this one qualifies. + if (!PrimaryBase) { + PrimaryBase = BaseDecl; + LeadsWithZeroSizedBase = BaseLayout.leadsWithZeroSizedBase(); + } + // Lay out the base. + layoutNonVirtualBase(BaseDecl, BaseLayout, PreviousBaseLayout); } - - // Use LayoutFields to compute the alignment of the fields. The layout - // is discarded. This is the simplest way to get all of the bit-field - // behavior correct and is not actually very expensive. - layoutFields(RD); - Size = CharUnits::Zero(); - BasesAndFieldsAlignment = Alignment; - FieldOffsets.clear(); -} - -void MicrosoftRecordLayoutBuilder::layoutVFPtr(const CXXRecordDecl *RD) { - // If we have a primary base then our VFPtr was already laid out - if (PrimaryBase) - return; - - // Look at all of our methods to determine if we need a VFPtr. We need a - // vfptr if we define a new virtual function. - if (!HasExtendableVFPtr && RD->isDynamicClass()) + // Figure out if we need a fresh VFPtr for this class. + if (!PrimaryBase && RD->isDynamicClass()) for (CXXRecordDecl::method_iterator i = RD->method_begin(), e = RD->method_end(); - !HasExtendableVFPtr && i != e; ++i) - HasExtendableVFPtr = i->isVirtual() && i->size_overridden_methods() == 0; - if (!HasExtendableVFPtr) - return; - - // MSVC 32 (but not 64) potentially over-aligns the vf-table pointer by giving - // it the max alignment of all the non-virtual data in the class. The - // resulting layout is essentially { vftbl, { nvdata } }. This is completely - // unnecessary, but we're not here to pass judgment. - updateAlignment(PointerAlignment); - if (Is64BitMode) - Size = Size.RoundUpToAlignment(PointerAlignment) + PointerSize; - else - Size = Size.RoundUpToAlignment(PointerAlignment) + Alignment; -} - -void -MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { - LazyEmptyBase = 0; - LastBaseWasEmpty = false; - LastNonVirtualBaseHasVBPtr = false; - - // Lay out the primary base first. - if (PrimaryBase) - layoutNonVirtualBase(PrimaryBase); - + !HasOwnVFPtr && i != e; ++i) + HasOwnVFPtr = i->isVirtual() && i->size_overridden_methods() == 0; + // If we don't have a primary base then we have a leading object that could + // itself lead with a zero-sized object, something we track. + bool CheckLeadingLayout = !PrimaryBase; // Iterate through the bases and lay out the non-virtual ones. - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); - i != e; ++i) { - if (i->isVirtual()) + for (const CXXBaseSpecifier &Base : RD->bases()) { + if (Base.isVirtual()) + continue; + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); + const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl); + // Only lay out bases without extendable VFPtrs on the second pass. + if (BaseLayout.hasExtendableVFPtr()) { + VBPtrOffset = Bases[BaseDecl] + BaseLayout.getNonVirtualSize(); continue; - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(i->getType()->castAs<RecordType>()->getDecl()); - if (BaseDecl != PrimaryBase) - layoutNonVirtualBase(BaseDecl); - } -} - -void -MicrosoftRecordLayoutBuilder::layoutNonVirtualBase(const CXXRecordDecl *RD) { - const ASTRecordLayout *Layout = RD ? &Context.getASTRecordLayout(RD) : 0; - - // If we have a lazy empty base we haven't laid out yet, do that now. - if (LazyEmptyBase) { - const ASTRecordLayout &LazyLayout = - Context.getASTRecordLayout(LazyEmptyBase); - Size = Size.RoundUpToAlignment(LazyLayout.getAlignment()); - // If the last non-virtual base has a vbptr we add a byte of padding for no - // obvious reason. - if (LastNonVirtualBaseHasVBPtr) - Size++; - Bases.insert(std::make_pair(LazyEmptyBase, Size)); - // Empty bases only consume space when followed by another empty base. - if (RD && Layout->getNonVirtualSize().isZero()) { - LastBaseWasEmpty = true; - Size++; } - LazyEmptyBase = 0; - LastNonVirtualBaseHasVBPtr = false; - } - - // RD is null when flushing the final lazy base. - if (!RD) - return; - - if (Layout->getNonVirtualSize().isZero()) { - LazyEmptyBase = RD; - return; + // If this is the first layout, check to see if it leads with a zero sized + // object. If it does, so do we. + if (CheckLeadingLayout) { + CheckLeadingLayout = false; + LeadsWithZeroSizedBase = BaseLayout.leadsWithZeroSizedBase(); + } + // Lay out the base. + layoutNonVirtualBase(BaseDecl, BaseLayout, PreviousBaseLayout); + VBPtrOffset = Bases[BaseDecl] + BaseLayout.getNonVirtualSize(); } - - // Insert the base here. - CharUnits BaseOffset = Size.RoundUpToAlignment(Layout->getAlignment()); - Bases.insert(std::make_pair(RD, BaseOffset)); - Size = BaseOffset + Layout->getDataSize(); - // Note: we don't update alignment here because it was accounted - // for during initalization. - LastBaseWasEmpty = false; - LastNonVirtualBaseHasVBPtr = Layout->hasVBPtr(); -} - -void MicrosoftRecordLayoutBuilder::layoutVBPtr(const CXXRecordDecl *RD) { + // Set our VBPtroffset if we know it at this point. if (!HasVBPtr) VBPtrOffset = CharUnits::fromQuantity(-1); else if (SharedVBPtrBase) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(SharedVBPtrBase); VBPtrOffset = Bases[SharedVBPtrBase] + Layout.getVBPtrOffset(); - } else { - VBPtrOffset = Size.RoundUpToAlignment(PointerAlignment); - CharUnits OldSize = Size; - Size = VBPtrOffset + PointerSize; - if (BasesAndFieldsAlignment <= PointerAlignment) { - // Handle strange padding rules for the lazily placed base. I have no - // explanation for why the last virtual base is padded in such an odd way. - // Two things to note about this padding are that the rules are different - // if the alignment of the bases+fields is <= to the alignemnt of a - // pointer and that the rule in 64-bit mode behaves differently depending - // on if the second to last base was also zero sized. - Size += OldSize % BasesAndFieldsAlignment.getQuantity(); - } else { - if (Is64BitMode) - Size += LastBaseWasEmpty ? CharUnits::One() : CharUnits::Zero(); - else - Size = OldSize + BasesAndFieldsAlignment; - } - updateAlignment(PointerAlignment); } +} - // Flush the lazy empty base. - layoutNonVirtualBase(0); +void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase( + const CXXRecordDecl *BaseDecl, + const ASTRecordLayout &BaseLayout, + const ASTRecordLayout *&PreviousBaseLayout) { + // Insert padding between two bases if the left first one is zero sized or + // contains a zero sized subobject and the right is zero sized or one leads + // with a zero sized base. + if (PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() && + BaseLayout.leadsWithZeroSizedBase()) + Size++; + ElementInfo Info = getAdjustedElementInfo(BaseLayout); + CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment); + Bases.insert(std::make_pair(BaseDecl, BaseOffset)); + Size = BaseOffset + BaseLayout.getNonVirtualSize(); + PreviousBaseLayout = &BaseLayout; } void MicrosoftRecordLayoutBuilder::layoutFields(const RecordDecl *RD) { LastFieldIsNonZeroWidthBitfield = false; - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); - Field != FieldEnd; ++Field) - layoutField(*Field); - Size = Size.RoundUpToAlignment(Alignment); + for (const FieldDecl *Field : RD->fields()) + layoutField(Field); } void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) { @@ -2415,20 +2465,15 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) { return; } LastFieldIsNonZeroWidthBitfield = false; - - std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD); - CharUnits FieldSize = FieldInfo.first; - CharUnits FieldAlign = FieldInfo.second; - - updateAlignment(FieldAlign); + ElementInfo Info = getAdjustedElementInfo(FD); + Alignment = std::max(Alignment, Info.Alignment); if (IsUnion) { - placeFieldAtZero(); - Size = std::max(Size, FieldSize); + placeFieldAtOffset(CharUnits::Zero()); + Size = std::max(Size, Info.Size); } else { - // Round up the current record size to the field's alignment boundary. - CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign); + CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment); placeFieldAtOffset(FieldOffset); - Size = FieldOffset + FieldSize; + Size = FieldOffset + Info.Size; } } @@ -2438,39 +2483,33 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { layoutZeroWidthBitField(FD); return; } - - std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD); - CharUnits FieldSize = FieldInfo.first; - CharUnits FieldAlign = FieldInfo.second; - + ElementInfo Info = getAdjustedElementInfo(FD); // Clamp the bitfield to a containable size for the sake of being able // to lay them out. Sema will throw an error. - if (Width > Context.toBits(FieldSize)) - Width = Context.toBits(FieldSize); - + if (Width > Context.toBits(Info.Size)) + Width = Context.toBits(Info.Size); // Check to see if this bitfield fits into an existing allocation. Note: // MSVC refuses to pack bitfields of formal types with different sizes // into the same allocation. if (!IsUnion && LastFieldIsNonZeroWidthBitfield && - CurrentBitfieldSize == FieldSize && Width <= RemainingBitsInField) { + CurrentBitfieldSize == Info.Size && Width <= RemainingBitsInField) { placeFieldAtBitOffset(Context.toBits(Size) - RemainingBitsInField); RemainingBitsInField -= Width; return; } - LastFieldIsNonZeroWidthBitfield = true; - CurrentBitfieldSize = FieldSize; + CurrentBitfieldSize = Info.Size; if (IsUnion) { - placeFieldAtZero(); - Size = std::max(Size, FieldSize); + placeFieldAtOffset(CharUnits::Zero()); + Size = std::max(Size, Info.Size); // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. } else { // Allocate a new block of memory and place the bitfield in it. - CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign); + CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment); placeFieldAtOffset(FieldOffset); - Size = FieldOffset + FieldSize; - updateAlignment(FieldAlign); - RemainingBitsInField = Context.toBits(FieldSize) - Width; + Size = FieldOffset + Info.Size; + Alignment = std::max(Alignment, Info.Alignment); + RemainingBitsInField = Context.toBits(Info.Size) - Width; } } @@ -2478,201 +2517,220 @@ void MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) { // Zero-width bitfields are ignored unless they follow a non-zero-width // bitfield. - std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD); - CharUnits FieldSize = FieldInfo.first; - CharUnits FieldAlign = FieldInfo.second; - if (!LastFieldIsNonZeroWidthBitfield) { placeFieldAtOffset(IsUnion ? CharUnits::Zero() : Size); // TODO: Add a Sema warning that MS ignores alignment for zero - // sized bitfields that occur after zero-size bitfields or non bitfields. + // sized bitfields that occur after zero-size bitfields or non-bitfields. return; } - LastFieldIsNonZeroWidthBitfield = false; + ElementInfo Info = getAdjustedElementInfo(FD); if (IsUnion) { - placeFieldAtZero(); - Size = std::max(Size, FieldSize); + placeFieldAtOffset(CharUnits::Zero()); + Size = std::max(Size, Info.Size); + // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. } else { // Round up the current record size to the field's alignment boundary. - CharUnits FieldOffset = Size.RoundUpToAlignment(FieldAlign); + CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment); placeFieldAtOffset(FieldOffset); Size = FieldOffset; - updateAlignment(FieldAlign); + Alignment = std::max(Alignment, Info.Alignment); } } +void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) { + if (!HasVBPtr || SharedVBPtrBase) + return; + // Inject the VBPointer at the injection site. + CharUnits InjectionSite = VBPtrOffset; + // But before we do, make sure it's properly aligned. + VBPtrOffset = VBPtrOffset.RoundUpToAlignment(PointerInfo.Alignment); + // Determine where the first field should be laid out after the vbptr. + CharUnits FieldStart = VBPtrOffset + PointerInfo.Size; + // Make sure that the amount we push the fields back by is a multiple of the + // alignment. + CharUnits Offset = (FieldStart - InjectionSite).RoundUpToAlignment( + std::max(RequiredAlignment, Alignment)); + // Increase the size of the object and push back all fields by the offset + // amount. + Size += Offset; + for (uint64_t &FieldOffset : FieldOffsets) + FieldOffset += Context.toBits(Offset); + for (BaseOffsetsMapTy::value_type &Base : Bases) + if (Base.second >= InjectionSite) + Base.second += Offset; +} + +void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) { + if (!HasOwnVFPtr) + return; + // Make sure that the amount we push the struct back by is a multiple of the + // alignment. + CharUnits Offset = PointerInfo.Size.RoundUpToAlignment( + std::max(RequiredAlignment, Alignment)); + // Increase the size of the object and push back all fields, the vbptr and all + // bases by the offset amount. + Size += Offset; + for (uint64_t &FieldOffset : FieldOffsets) + FieldOffset += Context.toBits(Offset); + if (HasVBPtr) + VBPtrOffset += Offset; + for (BaseOffsetsMapTy::value_type &Base : Bases) + Base.second += Offset; +} + void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { if (!HasVBPtr) return; - - updateAlignment(VirtualAlignment); - - // Zero-sized v-bases obey the alignment attribute so apply it here. The - // alignment attribute is normally accounted for in FinalizeLayout. - if (unsigned MaxAlign = RD->getMaxAlignment()) - updateAlignment(Context.toCharUnitsFromBits(MaxAlign)); - - llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordisp = + // Vtordisps are always 4 bytes (even in 64-bit mode) + CharUnits VtorDispSize = CharUnits::fromQuantity(4); + CharUnits VtorDispAlignment = VtorDispSize; + // vtordisps respect pragma pack. + if (!MaxFieldAlignment.isZero()) + VtorDispAlignment = std::min(VtorDispAlignment, MaxFieldAlignment); + // The alignment of the vtordisp is at least the required alignment of the + // entire record. This requirement may be present to support vtordisp + // injection. + for (const CXXBaseSpecifier &VBase : RD->vbases()) { + const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl(); + const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl); + RequiredAlignment = + std::max(RequiredAlignment, BaseLayout.getRequiredAlignment()); + } + VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment); + // Compute the vtordisp set. + llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordispSet = computeVtorDispSet(RD); - - // If the last field we laid out was a non-zero length bitfield then add some - // extra padding for no obvious reason. - if (LastFieldIsNonZeroWidthBitfield) - Size += CurrentBitfieldSize; - // Iterate through the virtual bases and lay them out. - for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(), - e = RD->vbases_end(); - i != e; ++i) { - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(i->getType()->castAs<RecordType>()->getDecl()); - layoutVirtualBase(BaseDecl, HasVtordisp.count(BaseDecl)); - } -} - -void MicrosoftRecordLayoutBuilder::layoutVirtualBase(const CXXRecordDecl *RD, - bool HasVtordisp) { - if (LazyEmptyBase) { - const ASTRecordLayout &LazyLayout = - Context.getASTRecordLayout(LazyEmptyBase); - Size = Size.RoundUpToAlignment(LazyLayout.getAlignment()); - VBases.insert( - std::make_pair(LazyEmptyBase, ASTRecordLayout::VBaseInfo(Size, false))); - // Empty bases only consume space when followed by another empty base. - // The space consumed is in an Alignment sized/aligned block and the v-base - // is placed at its alignment offset into the chunk, unless its alignment - // is less than 4 bytes, at which it is placed at 4 byte offset in the - // chunk. We have no idea why. - if (RD && Context.getASTRecordLayout(RD).getNonVirtualSize().isZero()) - Size = Size.RoundUpToAlignment(Alignment) + CharUnits::fromQuantity(4); - LazyEmptyBase = 0; - } - - // RD is null when flushing the final lazy virtual base. - if (!RD) - return; - - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - if (Layout.getNonVirtualSize().isZero() && !HasVtordisp) { - LazyEmptyBase = RD; - return; + const ASTRecordLayout *PreviousBaseLayout = nullptr; + for (const CXXBaseSpecifier &VBase : RD->vbases()) { + const CXXRecordDecl *BaseDecl = VBase.getType()->getAsCXXRecordDecl(); + const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl); + bool HasVtordisp = HasVtordispSet.count(BaseDecl); + // Insert padding between two bases if the left first one is zero sized or + // contains a zero sized subobject and the right is zero sized or one leads + // with a zero sized base. The padding between virtual bases is 4 + // bytes (in both 32 and 64 bits modes) and always involves rounding up to + // the required alignment, we don't know why. + if ((PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() && + BaseLayout.leadsWithZeroSizedBase()) || HasVtordisp) { + Size = Size.RoundUpToAlignment(VtorDispAlignment) + VtorDispSize; + Alignment = std::max(VtorDispAlignment, Alignment); + } + // Insert the virtual base. + ElementInfo Info = getAdjustedElementInfo(BaseLayout); + CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment); + VBases.insert(std::make_pair(BaseDecl, + ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp))); + Size = BaseOffset + BaseLayout.getNonVirtualSize(); + PreviousBaseLayout = &BaseLayout; } - - CharUnits BaseNVSize = Layout.getNonVirtualSize(); - CharUnits BaseAlign = Layout.getAlignment(); - - // vtordisps are always 4 bytes (even in 64-bit mode) - if (HasVtordisp) - Size = Size.RoundUpToAlignment(Alignment) + CharUnits::fromQuantity(4); - Size = Size.RoundUpToAlignment(BaseAlign); - - // Insert the base here. - CharUnits BaseOffset = Size.RoundUpToAlignment(BaseAlign); - VBases.insert( - std::make_pair(RD, ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp))); - Size = BaseOffset + BaseNVSize; - // Note: we don't update alignment here because it was accounted for in - // InitializeLayout. } -void MicrosoftRecordLayoutBuilder::finalizeCXXLayout(const CXXRecordDecl *RD) { - // Flush the lazy virtual base. - layoutVirtualBase(0, false); - - if (RD->vbases_begin() == RD->vbases_end() || AlignAfterVBases) - Size = Size.RoundUpToAlignment(Alignment); - - if (Size.isZero()) +void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) { + // Respect required alignment. Note that in 32-bit mode Required alignment + // may be 0 nad cause size not to be updated. + DataSize = Size; + if (!RequiredAlignment.isZero()) { + Alignment = std::max(Alignment, RequiredAlignment); + auto RoundingAlignment = Alignment; + if (!MaxFieldAlignment.isZero()) + RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment); + RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment); + Size = Size.RoundUpToAlignment(RoundingAlignment); + } + // Zero-sized structures have size equal to their alignment. + if (Size.isZero()) { + EndsWithZeroSizedObject = true; + LeadsWithZeroSizedBase = true; Size = Alignment; -} - -void MicrosoftRecordLayoutBuilder::honorDeclspecAlign(const RecordDecl *RD) { - if (unsigned MaxAlign = RD->getMaxAlignment()) { - AlignAfterVBases = true; - updateAlignment(Context.toCharUnitsFromBits(MaxAlign)); - Size = Size.RoundUpToAlignment(Alignment); } } +// Recursively walks the non-virtual bases of a class and determines if any of +// them are in the bases with overridden methods set. static bool -RequiresVtordisp(const llvm::SmallPtrSet<const CXXRecordDecl *, 2> &HasVtordisp, +RequiresVtordisp(const llvm::SmallPtrSetImpl<const CXXRecordDecl *> & + BasesWithOverriddenMethods, const CXXRecordDecl *RD) { - if (HasVtordisp.count(RD)) + if (BasesWithOverriddenMethods.count(RD)) return true; // If any of a virtual bases non-virtual bases (recursively) requires a // vtordisp than so does this virtual base. - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); - i != e; ++i) - if (!i->isVirtual() && - RequiresVtordisp( - HasVtordisp, - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()))) + for (const CXXBaseSpecifier &Base : RD->bases()) + if (!Base.isVirtual() && + RequiresVtordisp(BasesWithOverriddenMethods, + Base.getType()->getAsCXXRecordDecl())) return true; return false; } llvm::SmallPtrSet<const CXXRecordDecl *, 2> MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) { - llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordisp; + llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordispSet; + + // /vd2 or #pragma vtordisp(2): Always use vtordisps for virtual bases with + // vftables. + if (RD->getMSVtorDispMode() == MSVtorDispAttr::ForVFTable) { + for (const CXXBaseSpecifier &Base : RD->vbases()) { + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl); + if (Layout.hasExtendableVFPtr()) + HasVtordispSet.insert(BaseDecl); + } + return HasVtordispSet; + } // If any of our bases need a vtordisp for this type, so do we. Check our // direct bases for vtordisp requirements. - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); - i != e; ++i) { - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + for (const CXXBaseSpecifier &Base : RD->bases()) { + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(BaseDecl); - for (ASTRecordLayout::VBaseOffsetsMapTy::const_iterator - bi = Layout.getVBaseOffsetsMap().begin(), - be = Layout.getVBaseOffsetsMap().end(); - bi != be; ++bi) - if (bi->second.hasVtorDisp()) - HasVtordisp.insert(bi->first); - } - - // If we define a constructor or destructor and override a function that is - // defined in a virtual base's vtable, that virtual bases need a vtordisp. - // Here we collect a list of classes with vtables for which our virtual bases - // actually live. The virtual bases with this property will require - // vtordisps. In addition, virtual bases that contain non-virtual bases that - // define functions we override also require vtordisps, this case is checked - // explicitly below. - if (RD->hasUserDeclaredConstructor() || RD->hasUserDeclaredDestructor()) { - llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work; - // Seed the working set with our non-destructor virtual methods. - for (CXXRecordDecl::method_iterator i = RD->method_begin(), - e = RD->method_end(); - i != e; ++i) - if ((*i)->isVirtual() && !isa<CXXDestructorDecl>(*i)) - Work.insert(*i); - while (!Work.empty()) { - const CXXMethodDecl *MD = *Work.begin(); - CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(), - e = MD->end_overridden_methods(); - if (i == e) - // If a virtual method has no-overrides it lives in its parent's vtable. - HasVtordisp.insert(MD->getParent()); - else - Work.insert(i, e); - // We've finished processing this element, remove it from the working set. - Work.erase(MD); - } + for (const auto &bi : Layout.getVBaseOffsetsMap()) + if (bi.second.hasVtorDisp()) + HasVtordispSet.insert(bi.first); + } + // We don't introduce any additional vtordisps if either: + // * A user declared constructor or destructor aren't declared. + // * #pragma vtordisp(0) or the /vd0 flag are in use. + if ((!RD->hasUserDeclaredConstructor() && !RD->hasUserDeclaredDestructor()) || + RD->getMSVtorDispMode() == MSVtorDispAttr::Never) + return HasVtordispSet; + // /vd1 or #pragma vtordisp(1): Try to guess based on whether we think it's + // possible for a partially constructed object with virtual base overrides to + // escape a non-trivial constructor. + assert(RD->getMSVtorDispMode() == MSVtorDispAttr::ForVBaseOverride); + // Compute a set of base classes which define methods we override. A virtual + // base in this set will require a vtordisp. A virtual base that transitively + // contains one of these bases as a non-virtual base will also require a + // vtordisp. + llvm::SmallPtrSet<const CXXMethodDecl *, 8> Work; + llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods; + // Seed the working set with our non-destructor virtual methods. + for (const CXXMethodDecl *MD : RD->methods()) + if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) + Work.insert(MD); + while (!Work.empty()) { + const CXXMethodDecl *MD = *Work.begin(); + CXXMethodDecl::method_iterator i = MD->begin_overridden_methods(), + e = MD->end_overridden_methods(); + // If a virtual method has no-overrides it lives in its parent's vtable. + if (i == e) + BasesWithOverriddenMethods.insert(MD->getParent()); + else + Work.insert(i, e); + // We've finished processing this element, remove it from the working set. + Work.erase(MD); } - - // Re-check all of our vbases for vtordisp requirements (in case their - // non-virtual bases have vtordisp requirements). - for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(), - e = RD->vbases_end(); - i != e; ++i) { - const CXXRecordDecl *BaseDecl = i->getType()->getAsCXXRecordDecl(); - if (!HasVtordisp.count(BaseDecl) && RequiresVtordisp(HasVtordisp, BaseDecl)) - HasVtordisp.insert(BaseDecl); + // For each of our virtual bases, check if it is in the set of overridden + // bases or if it transitively contains a non-virtual base that is. + for (const CXXBaseSpecifier &Base : RD->vbases()) { + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); + if (!HasVtordispSet.count(BaseDecl) && + RequiresVtordisp(BasesWithOverriddenMethods, BaseDecl)) + HasVtordispSet.insert(BaseDecl); } - - return HasVtordisp; + return HasVtordispSet; } /// \brief Get or compute information about the layout of the specified record @@ -2684,19 +2742,20 @@ ASTContext::BuildMicrosoftASTRecordLayout(const RecordDecl *D) const { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { Builder.cxxLayout(RD); return new (*this) ASTRecordLayout( - *this, Builder.Size, Builder.Alignment, - Builder.HasExtendableVFPtr && !Builder.PrimaryBase, - Builder.HasExtendableVFPtr, - Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets.data(), - Builder.FieldOffsets.size(), Builder.DataSize, - Builder.NonVirtualAlignment, CharUnits::Zero(), Builder.PrimaryBase, - false, Builder.SharedVBPtrBase, Builder.AlignAfterVBases, Builder.Bases, - Builder.VBases); + *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment, + Builder.HasOwnVFPtr, + Builder.HasOwnVFPtr || Builder.PrimaryBase, + Builder.VBPtrOffset, Builder.NonVirtualSize, Builder.FieldOffsets.data(), + Builder.FieldOffsets.size(), Builder.NonVirtualSize, + Builder.Alignment, CharUnits::Zero(), Builder.PrimaryBase, + false, Builder.SharedVBPtrBase, + Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase, + Builder.Bases, Builder.VBases); } else { Builder.layout(D); return new (*this) ASTRecordLayout( - *this, Builder.Size, Builder.Alignment, Builder.Size, - Builder.FieldOffsets.data(), Builder.FieldOffsets.size()); + *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment, + Builder.Size, Builder.FieldOffsets.data(), Builder.FieldOffsets.size()); } } @@ -2724,7 +2783,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *Entry = ASTRecordLayouts[D]; if (Entry) return *Entry; - const ASTRecordLayout *NewEntry = 0; + const ASTRecordLayout *NewEntry = nullptr; if (isMsLayout(D) && !D->getASTContext().getExternalSource()) { NewEntry = BuildMicrosoftASTRecordLayout(D); @@ -2747,6 +2806,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { NewEntry = new (*this) ASTRecordLayout(*this, Builder.getSize(), Builder.Alignment, + /*RequiredAlignment : used by MS-ABI)*/ + Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(), CharUnits::fromQuantity(-1), @@ -2758,15 +2819,17 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase, Builder.PrimaryBaseIsVirtual, - 0, true, + nullptr, false, false, Builder.Bases, Builder.VBases); } else { - RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0); + RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr); Builder.Layout(D); NewEntry = new (*this) ASTRecordLayout(*this, Builder.getSize(), Builder.Alignment, + /*RequiredAlignment : used by MS-ABI)*/ + Builder.Alignment, Builder.getSize(), Builder.FieldOffsets.data(), Builder.FieldOffsets.size()); @@ -2784,16 +2847,25 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) { if (!getTargetInfo().getCXXABI().hasKeyFunctions()) - return 0; + return nullptr; assert(RD->getDefinition() && "Cannot get key function for forward decl!"); RD = cast<CXXRecordDecl>(RD->getDefinition()); - LazyDeclPtr &Entry = KeyFunctions[RD]; - if (!Entry) - Entry = const_cast<CXXMethodDecl*>(computeKeyFunction(*this, RD)); + // Beware: + // 1) computing the key function might trigger deserialization, which might + // invalidate iterators into KeyFunctions + // 2) 'get' on the LazyDeclPtr might also trigger deserialization and + // invalidate the LazyDeclPtr within the map itself + LazyDeclPtr Entry = KeyFunctions[RD]; + const Decl *Result = + Entry ? Entry.get(getExternalSource()) : computeKeyFunction(*this, RD); + + // Store it back if it changed. + if (Entry.isOffset() || Entry.isValid() != bool(Result)) + KeyFunctions[RD] = const_cast<Decl*>(Result); - return cast_or_null<CXXMethodDecl>(Entry.get(getExternalSource())); + return cast_or_null<CXXMethodDecl>(Result); } void ASTContext::setNonKeyFunction(const CXXMethodDecl *Method) { @@ -2810,10 +2882,12 @@ void ASTContext::setNonKeyFunction(const CXXMethodDecl *Method) { if (I == KeyFunctions.end()) return; // If it is cached, check whether it's the target method, and if so, - // remove it from the cache. - if (I->second.get(getExternalSource()) == Method) { + // remove it from the cache. Note, the call to 'get' might invalidate + // the iterator and the LazyDeclPtr object within the map. + LazyDeclPtr Ptr = I->second; + if (Ptr.get(getExternalSource()) == Method) { // FIXME: remember that we did this for module / chained PCH state? - KeyFunctions.erase(I); + KeyFunctions.erase(Method->getParent()); } } @@ -2830,10 +2904,8 @@ uint64_t ASTContext::getFieldOffset(const ValueDecl *VD) const { const IndirectFieldDecl *IFD = cast<IndirectFieldDecl>(VD); OffsetInBits = 0; - for (IndirectFieldDecl::chain_iterator CI = IFD->chain_begin(), - CE = IFD->chain_end(); - CI != CE; ++CI) - OffsetInBits += ::getFieldOffset(*this, cast<FieldDecl>(*CI)); + for (const NamedDecl *ND : IFD->chain()) + OffsetInBits += ::getFieldOffset(*this, cast<FieldDecl>(ND)); } return OffsetInBits; @@ -2867,15 +2939,17 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, // entries later; however we shouldn't look up implementations // frequently. if (SynthCount == 0) - return getObjCLayout(D, 0); + return getObjCLayout(D, nullptr); } - RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0); + RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr); Builder.Layout(D); const ASTRecordLayout *NewEntry = new (*this) ASTRecordLayout(*this, Builder.getSize(), Builder.Alignment, + /*RequiredAlignment : used by MS-ABI)*/ + Builder.Alignment, Builder.getDataSize(), Builder.FieldOffsets.data(), Builder.FieldOffsets.size()); @@ -2928,19 +3002,24 @@ static void DumpCXXRecordLayout(raw_ostream &OS, OS << '(' << *RD << " vftable pointer)\n"; } - // Dump (non-virtual) bases - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && + // Collect nvbases. + SmallVector<const CXXRecordDecl *, 4> Bases; + for (const CXXBaseSpecifier &Base : RD->bases()) { + assert(!Base.getType()->isDependentType() && "Cannot layout class with dependent bases."); - if (I->isVirtual()) - continue; + if (!Base.isVirtual()) + Bases.push_back(Base.getType()->getAsCXXRecordDecl()); + } - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + // Sort nvbases by offset. + std::stable_sort(Bases.begin(), Bases.end(), + [&](const CXXRecordDecl *L, const CXXRecordDecl *R) { + return Layout.getBaseClassOffset(L) < Layout.getBaseClassOffset(R); + }); + // Dump (non-virtual) bases + for (const CXXRecordDecl *Base : Bases) { CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base); - DumpCXXRecordLayout(OS, Base, C, BaseOffset, IndentLevel, Base == PrimaryBase ? "(primary base)" : "(base)", /*IncludeVirtualBases=*/false); @@ -2960,13 +3039,11 @@ static void DumpCXXRecordLayout(raw_ostream &OS, CharUnits FieldOffset = Offset + C.toCharUnitsFromBits(Layout.getFieldOffset(FieldNo)); - if (const RecordType *RT = Field.getType()->getAs<RecordType>()) { - if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel, - Field.getName().data(), - /*IncludeVirtualBases=*/true); - continue; - } + if (const CXXRecordDecl *D = Field.getType()->getAsCXXRecordDecl()) { + DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel, + Field.getName().data(), + /*IncludeVirtualBases=*/true); + continue; } PrintOffset(OS, FieldOffset, IndentLevel); @@ -2979,11 +3056,9 @@ static void DumpCXXRecordLayout(raw_ostream &OS, // Dump virtual bases. const ASTRecordLayout::VBaseOffsetsMapTy &vtordisps = Layout.getVBaseOffsetsMap(); - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { - assert(I->isVirtual() && "Found non-virtual class!"); - const CXXRecordDecl *VBase = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + for (const CXXBaseSpecifier &Base : RD->vbases()) { + assert(Base.isVirtual() && "Found non-virtual class!"); + const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl(); CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase); @@ -3006,8 +3081,7 @@ static void DumpCXXRecordLayout(raw_ostream &OS, PrintIndentNoOffset(OS, IndentLevel - 1); OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity(); - OS << ", nvalign=" << Layout.getNonVirtualAlign().getQuantity() << "]\n"; - OS << '\n'; + OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity() << "]\n"; } void ASTContext::DumpRecordLayout(const RecordDecl *RD, @@ -3017,7 +3091,7 @@ void ASTContext::DumpRecordLayout(const RecordDecl *RD, if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) if (!Simple) - return DumpCXXRecordLayout(OS, CXXRD, *this, CharUnits(), 0, 0, + return DumpCXXRecordLayout(OS, CXXRD, *this, CharUnits(), 0, nullptr, /*IncludeVirtualBases=*/true); OS << "Type: " << getTypeDeclType(RD).getAsString() << "\n"; diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index de85161..a8483dc 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -65,13 +65,13 @@ void Stmt::PrintStats() { unsigned sum = 0; llvm::errs() << "\n*** Stmt/Expr Stats:\n"; for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { - if (StmtClassInfo[i].Name == 0) continue; + if (StmtClassInfo[i].Name == nullptr) continue; sum += StmtClassInfo[i].Counter; } llvm::errs() << " " << sum << " stmts/exprs total.\n"; sum = 0; for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { - if (StmtClassInfo[i].Name == 0) continue; + if (StmtClassInfo[i].Name == nullptr) continue; if (StmtClassInfo[i].Counter == 0) continue; llvm::errs() << " " << StmtClassInfo[i].Counter << " " << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size @@ -260,7 +260,7 @@ CompoundStmt::CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts, "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); if (Stmts.size() == 0) { - Body = 0; + Body = nullptr; return; } @@ -285,8 +285,8 @@ const char *LabelStmt::getName() const { AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt) { - void *Mem = C.Allocate(sizeof(AttributedStmt) + - sizeof(Attr*) * (Attrs.size() - 1), + assert(!Attrs.empty() && "Attrs should not be empty"); + void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * Attrs.size(), llvm::alignOf<AttributedStmt>()); return new (Mem) AttributedStmt(Loc, Attrs, SubStmt); } @@ -294,8 +294,7 @@ AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc, AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C, unsigned NumAttrs) { assert(NumAttrs > 0 && "NumAttrs should be greater than zero"); - void *Mem = C.Allocate(sizeof(AttributedStmt) + - sizeof(Attr*) * (NumAttrs - 1), + void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * NumAttrs, llvm::alignOf<AttributedStmt>()); return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); } @@ -554,7 +553,7 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, // Find the ']'. const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr); - if (NameEnd == 0) + if (NameEnd == nullptr) return diag::err_asm_unterminated_symbolic_operand_name; if (NameEnd == CurPtr) return diag::err_asm_empty_symbolic_operand_name; @@ -720,8 +719,7 @@ ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, Stmt **CatchStmts, unsigned NumCatchStmts, Stmt *atFinallyStmt) : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc), - NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != 0) -{ + NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != nullptr) { Stmt **Stmts = getStmts(); Stmts[0] = atTryStmt; for (unsigned I = 0; I != NumCatchStmts; ++I) @@ -738,7 +736,7 @@ ObjCAtTryStmt *ObjCAtTryStmt::Create(const ASTContext &Context, unsigned NumCatchStmts, Stmt *atFinallyStmt) { unsigned Size = sizeof(ObjCAtTryStmt) + - (1 + NumCatchStmts + (atFinallyStmt != 0)) * sizeof(Stmt *); + (1 + NumCatchStmts + (atFinallyStmt != nullptr)) * sizeof(Stmt *); void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts, atFinallyStmt); @@ -803,7 +801,7 @@ CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt, Expr *CXXForRangeStmt::getRangeInit() { DeclStmt *RangeStmt = getRangeStmt(); VarDecl *RangeDecl = dyn_cast_or_null<VarDecl>(RangeStmt->getSingleDecl()); - assert(RangeDecl &&& "for-range should have a single var decl"); + assert(RangeDecl && "for-range should have a single var decl"); return RangeDecl->getInit(); } @@ -833,7 +831,7 @@ IfStmt::IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, VarDecl *IfStmt::getConditionVariable() const { if (!SubExprs[VAR]) - return 0; + return nullptr; DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); return cast<VarDecl>(DS->getSingleDecl()); @@ -841,7 +839,7 @@ VarDecl *IfStmt::getConditionVariable() const { void IfStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { if (!V) { - SubExprs[VAR] = 0; + SubExprs[VAR] = nullptr; return; } @@ -864,7 +862,7 @@ ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, VarDecl *ForStmt::getConditionVariable() const { if (!SubExprs[CONDVAR]) - return 0; + return nullptr; DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]); return cast<VarDecl>(DS->getSingleDecl()); @@ -872,7 +870,7 @@ VarDecl *ForStmt::getConditionVariable() const { void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { if (!V) { - SubExprs[CONDVAR] = 0; + SubExprs[CONDVAR] = nullptr; return; } @@ -882,16 +880,16 @@ void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { } SwitchStmt::SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond) - : Stmt(SwitchStmtClass), FirstCase(0), AllEnumCasesCovered(0) + : Stmt(SwitchStmtClass), FirstCase(nullptr), AllEnumCasesCovered(0) { setConditionVariable(C, Var); SubExprs[COND] = cond; - SubExprs[BODY] = NULL; + SubExprs[BODY] = nullptr; } VarDecl *SwitchStmt::getConditionVariable() const { if (!SubExprs[VAR]) - return 0; + return nullptr; DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); return cast<VarDecl>(DS->getSingleDecl()); @@ -899,7 +897,7 @@ VarDecl *SwitchStmt::getConditionVariable() const { void SwitchStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { if (!V) { - SubExprs[VAR] = 0; + SubExprs[VAR] = nullptr; return; } @@ -925,7 +923,7 @@ WhileStmt::WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, VarDecl *WhileStmt::getConditionVariable() const { if (!SubExprs[VAR]) - return 0; + return nullptr; DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); return cast<VarDecl>(DS->getSingleDecl()); @@ -933,7 +931,7 @@ VarDecl *WhileStmt::getConditionVariable() const { void WhileStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { if (!V) { - SubExprs[VAR] = 0; + SubExprs[VAR] = nullptr; return; } @@ -947,7 +945,7 @@ LabelDecl *IndirectGotoStmt::getConstantTarget() { if (AddrLabelExpr *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts())) return E->getLabel(); - return 0; + return nullptr; } // ReturnStmt @@ -958,22 +956,20 @@ Expr* ReturnStmt::getRetValue() { return cast_or_null<Expr>(RetExpr); } -SEHTryStmt::SEHTryStmt(bool IsCXXTry, - SourceLocation TryLoc, - Stmt *TryBlock, - Stmt *Handler) - : Stmt(SEHTryStmtClass), - IsCXXTry(IsCXXTry), - TryLoc(TryLoc) -{ - Children[TRY] = TryBlock; +SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, + Stmt *Handler, int HandlerIndex, int HandlerParentIndex) + : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc), + HandlerIndex(HandlerIndex), HandlerParentIndex(HandlerParentIndex) { + Children[TRY] = TryBlock; Children[HANDLER] = Handler; } -SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry, +SEHTryStmt *SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, - Stmt *Handler) { - return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler); + Stmt *Handler, int HandlerIndex, + int HandlerParentIndex) { + return new (C) SEHTryStmt(IsCXXTry, TryLoc, TryBlock, Handler, HandlerIndex, + HandlerParentIndex); } SEHExceptStmt* SEHTryStmt::getExceptHandler() const { @@ -1049,8 +1045,8 @@ CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind, CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures) : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures), - CapDeclAndKind(0, CR_Default), TheRecordDecl(0) { - getStoredStmts()[NumCaptures] = 0; + CapDeclAndKind(nullptr, CR_Default), TheRecordDecl(nullptr) { + getStoredStmts()[NumCaptures] = nullptr; } CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S, @@ -1100,15 +1096,14 @@ Stmt::child_range CapturedStmt::children() { } bool CapturedStmt::capturesVariable(const VarDecl *Var) const { - for (const_capture_iterator I = capture_begin(), - E = capture_end(); I != E; ++I) { - if (!I->capturesVariable()) + for (const auto &I : captures()) { + if (!I.capturesVariable()) continue; // This does not handle variable redeclarations. This should be // extended to capture variables with redeclarations, for example // a thread-private variable in OpenMP. - if (I->getCapturedVar() == Var) + if (I.getCapturedVar() == Var) return true; } @@ -1130,8 +1125,9 @@ OMPPrivateClause *OMPPrivateClause::Create(const ASTContext &C, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(sizeof(OMPPrivateClause) + sizeof(Expr *) * VL.size(), - llvm::alignOf<OMPPrivateClause>()); + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * VL.size()); OMPPrivateClause *Clause = new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); @@ -1140,8 +1136,9 @@ OMPPrivateClause *OMPPrivateClause::Create(const ASTContext &C, OMPPrivateClause *OMPPrivateClause::CreateEmpty(const ASTContext &C, unsigned N) { - void *Mem = C.Allocate(sizeof(OMPPrivateClause) + sizeof(Expr *) * N, - llvm::alignOf<OMPPrivateClause>()); + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * N); return new (Mem) OMPPrivateClause(N); } @@ -1150,9 +1147,9 @@ OMPFirstprivateClause *OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(sizeof(OMPFirstprivateClause) + - sizeof(Expr *) * VL.size(), - llvm::alignOf<OMPFirstprivateClause>()); + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFirstprivateClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * VL.size()); OMPFirstprivateClause *Clause = new (Mem) OMPFirstprivateClause(StartLoc, LParenLoc, EndLoc, @@ -1163,18 +1160,42 @@ OMPFirstprivateClause *OMPFirstprivateClause::Create(const ASTContext &C, OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C, unsigned N) { - void *Mem = C.Allocate(sizeof(OMPFirstprivateClause) + sizeof(Expr *) * N, - llvm::alignOf<OMPFirstprivateClause>()); + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFirstprivateClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * N); return new (Mem) OMPFirstprivateClause(N); } +OMPLastprivateClause *OMPLastprivateClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * VL.size()); + OMPLastprivateClause *Clause = + new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * N); + return new (Mem) OMPLastprivateClause(N); +} + OMPSharedClause *OMPSharedClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(sizeof(OMPSharedClause) + sizeof(Expr *) * VL.size(), - llvm::alignOf<OMPSharedClause>()); + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPSharedClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * VL.size()); OMPSharedClause *Clause = new (Mem) OMPSharedClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); @@ -1183,15 +1204,148 @@ OMPSharedClause *OMPSharedClause::Create(const ASTContext &C, OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C, unsigned N) { - void *Mem = C.Allocate(sizeof(OMPSharedClause) + sizeof(Expr *) * N, - llvm::alignOf<OMPSharedClause>()); + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPSharedClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * N); return new (Mem) OMPSharedClause(N); } +OMPLinearClause *OMPLinearClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL, Expr *Step) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * (VL.size() + 1)); + OMPLinearClause *Clause = new (Mem) + OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setStep(Step); + return Clause; +} + +OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C, + unsigned NumVars) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * (NumVars + 1)); + return new (Mem) OMPLinearClause(NumVars); +} + +OMPAlignedClause * +OMPAlignedClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, Expr *A) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPAlignedClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * (VL.size() + 1)); + OMPAlignedClause *Clause = new (Mem) + OMPAlignedClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setAlignment(A); + return Clause; +} + +OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C, + unsigned NumVars) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPAlignedClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * (NumVars + 1)); + return new (Mem) OMPAlignedClause(NumVars); +} + +OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * VL.size()); + OMPCopyinClause *Clause = new (Mem) OMPCopyinClause(StartLoc, LParenLoc, + EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * N); + return new (Mem) OMPCopyinClause(N); +} + +OMPCopyprivateClause *OMPCopyprivateClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * VL.size()); + OMPCopyprivateClause *Clause = + new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * N); + return new (Mem) OMPCopyprivateClause(N); +} + void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) { - assert(Clauses.size() == this->Clauses.size() && + assert(Clauses.size() == getNumClauses() && "Number of clauses is not the same as the preallocated buffer"); - std::copy(Clauses.begin(), Clauses.end(), this->Clauses.begin()); + std::copy(Clauses.begin(), Clauses.end(), getClauses().begin()); +} + +OMPReductionClause *OMPReductionClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * VL.size()); + OMPReductionClause *Clause = new (Mem) OMPReductionClause( + StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo); + Clause->setVarRefs(VL); + return Clause; +} + +OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * N); + return new (Mem) OMPReductionClause(N); +} + +OMPFlushClause *OMPFlushClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFlushClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * VL.size()); + OMPFlushClause *Clause = + new (Mem) OMPFlushClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) { + void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFlushClause), + llvm::alignOf<Expr *>()) + + sizeof(Expr *) * N); + return new (Mem) OMPFlushClause(N); } OMPParallelDirective *OMPParallelDirective::Create( @@ -1200,9 +1354,10 @@ OMPParallelDirective *OMPParallelDirective::Create( SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { - void *Mem = C.Allocate(sizeof(OMPParallelDirective) + - sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *), - llvm::alignOf<OMPParallelDirective>()); + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *)); OMPParallelDirective *Dir = new (Mem) OMPParallelDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); @@ -1211,10 +1366,315 @@ OMPParallelDirective *OMPParallelDirective::Create( } OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C, - unsigned N, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *)); + return new (Mem) OMPParallelDirective(NumClauses); +} + +OMPSimdDirective * +OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPSimdDirective *Dir = new (Mem) + OMPSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPSimdDirective(CollapsedNum, NumClauses); +} + +OMPForDirective * +OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPForDirective *Dir = + new (Mem) OMPForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPForDirective(CollapsedNum, NumClauses); +} + +OMPSectionsDirective *OMPSectionsDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPSectionsDirective *Dir = + new (Mem) OMPSectionsDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPSectionsDirective *OMPSectionsDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPSectionsDirective(NumClauses); +} + +OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + return new (Mem) OMPSectionDirective(); +} + +OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSingleDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPSingleDirective *Dir = + new (Mem) OMPSingleDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSingleDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPSingleDirective(NumClauses); +} + +OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPMasterDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + OMPMasterDirective *Dir = new (Mem) OMPMasterDirective(StartLoc, EndLoc); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPMasterDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + return new (Mem) OMPMasterDirective(); +} + +OMPCriticalDirective *OMPCriticalDirective::Create( + const ASTContext &C, const DeclarationNameInfo &Name, + SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + OMPCriticalDirective *Dir = + new (Mem) OMPCriticalDirective(Name, StartLoc, EndLoc); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + return new (Mem) OMPCriticalDirective(); +} + +OMPParallelForDirective * +OMPParallelForDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPParallelForDirective *Dir = new (Mem) + OMPParallelForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPParallelForDirective * +OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPParallelForDirective(CollapsedNum, NumClauses); +} + +OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelSectionsDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPParallelSectionsDirective *Dir = + new (Mem) OMPParallelSectionsDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPParallelSectionsDirective * +OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelSectionsDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPParallelSectionsDirective(NumClauses); +} + +OMPTaskDirective *OMPTaskDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTaskDirective *Dir = + new (Mem) OMPTaskDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTaskDirective(NumClauses); +} + +OMPTaskyieldDirective *OMPTaskyieldDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective)); + OMPTaskyieldDirective *Dir = + new (Mem) OMPTaskyieldDirective(StartLoc, EndLoc); + return Dir; +} + +OMPTaskyieldDirective *OMPTaskyieldDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective)); + return new (Mem) OMPTaskyieldDirective(); +} + +OMPBarrierDirective *OMPBarrierDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(OMPBarrierDirective)); + OMPBarrierDirective *Dir = new (Mem) OMPBarrierDirective(StartLoc, EndLoc); + return Dir; +} + +OMPBarrierDirective *OMPBarrierDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + void *Mem = C.Allocate(sizeof(OMPBarrierDirective)); + return new (Mem) OMPBarrierDirective(); +} + +OMPTaskwaitDirective *OMPTaskwaitDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(OMPTaskwaitDirective)); + OMPTaskwaitDirective *Dir = new (Mem) OMPTaskwaitDirective(StartLoc, EndLoc); + return Dir; +} + +OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - void *Mem = C.Allocate(sizeof(OMPParallelDirective) + - sizeof(OMPClause *) * N + sizeof(Stmt *), - llvm::alignOf<OMPParallelDirective>()); - return new (Mem) OMPParallelDirective(N); + void *Mem = C.Allocate(sizeof(OMPTaskwaitDirective)); + return new (Mem) OMPTaskwaitDirective(); +} + +OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPFlushDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size()); + OMPFlushDirective *Dir = + new (Mem) OMPFlushDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + return Dir; +} + +OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPFlushDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses); + return new (Mem) OMPFlushDirective(NumClauses); } + diff --git a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp index 6e85375..1ccba04 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp @@ -27,7 +27,7 @@ static inline const VariableArrayType *FindVA(const Type* t) { t = vt->getElementType().getTypePtr(); } - return NULL; + return nullptr; } void StmtIteratorBase::NextVA() { @@ -54,7 +54,7 @@ void StmtIteratorBase::NextVA() { } void StmtIteratorBase::NextDecl(bool ImmediateAdvance) { - assert (getVAPtr() == NULL); + assert(getVAPtr() == nullptr); assert(inDeclGroup()); if (ImmediateAdvance) @@ -93,12 +93,12 @@ bool StmtIteratorBase::HandleDecl(Decl* D) { } StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge) - : stmt(0), DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) { + : stmt(nullptr), DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) { NextDecl(false); } StmtIteratorBase::StmtIteratorBase(const VariableArrayType* t) - : stmt(0), DGI(0), RawVAPtr(SizeOfTypeVAMode) { + : stmt(nullptr), DGI(nullptr), RawVAPtr(SizeOfTypeVAMode) { RawVAPtr |= reinterpret_cast<uintptr_t>(t); } diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index ae2cdf7..1fdad9f 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -70,6 +70,7 @@ namespace { void PrintCallArgs(CallExpr *E); void PrintRawSEHExceptHandler(SEHExceptStmt *S); void PrintRawSEHFinallyStmt(SEHFinallyStmt *S); + void PrintOMPExecutableDirective(OMPExecutableDirective *S); void PrintExpr(Expr *E) { if (E) @@ -89,7 +90,7 @@ namespace { return; else StmtVisitor<StmtPrinter>::Visit(S); } - + void VisitStmt(Stmt *Node) LLVM_ATTRIBUTE_UNUSED { Indent() << "<<unknown stmt type>>\n"; } @@ -113,9 +114,8 @@ namespace { /// with no newline after the }. void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) { OS << "{\n"; - for (CompoundStmt::body_iterator I = Node->body_begin(), E = Node->body_end(); - I != E; ++I) - PrintStmt(*I); + for (auto *I : Node->body()) + PrintStmt(I); Indent() << "}"; } @@ -125,11 +125,7 @@ void StmtPrinter::PrintRawDecl(Decl *D) { } void StmtPrinter::PrintRawDeclStmt(const DeclStmt *S) { - DeclStmt::const_decl_iterator Begin = S->decl_begin(), End = S->decl_end(); - SmallVector<Decl*, 2> Decls; - for ( ; Begin != End; ++Begin) - Decls.push_back(*Begin); - + SmallVector<Decl*, 2> Decls(S->decls()); Decl::printGroup(Decls.data(), Decls.size(), OS, Policy, IndentLevel); } @@ -172,19 +168,10 @@ void StmtPrinter::VisitLabelStmt(LabelStmt *Node) { } void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) { - OS << "[["; - bool first = true; - for (ArrayRef<const Attr*>::iterator it = Node->getAttrs().begin(), - end = Node->getAttrs().end(); - it != end; ++it) { - if (!first) { - OS << ", "; - first = false; - } - // TODO: check this - (*it)->printPretty(OS, Policy); + for (const auto *Attr : Node->getAttrs()) { + Attr->printPretty(OS, Policy); } - OS << "]] "; + PrintStmt(Node->getSubStmt(), 0); } @@ -330,7 +317,8 @@ void StmtPrinter::VisitCXXForRangeStmt(CXXForRangeStmt *Node) { PrintExpr(Node->getRangeInit()); OS << ") {\n"; PrintStmt(Node->getBody()); - Indent() << "}\n"; + Indent() << "}"; + if (Policy.IncludeNewlines) OS << "\n"; } void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) { @@ -350,21 +338,25 @@ void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) { } void StmtPrinter::VisitGotoStmt(GotoStmt *Node) { - Indent() << "goto " << Node->getLabel()->getName() << ";\n"; + Indent() << "goto " << Node->getLabel()->getName() << ";"; + if (Policy.IncludeNewlines) OS << "\n"; } void StmtPrinter::VisitIndirectGotoStmt(IndirectGotoStmt *Node) { Indent() << "goto *"; PrintExpr(Node->getTarget()); - OS << ";\n"; + OS << ";"; + if (Policy.IncludeNewlines) OS << "\n"; } void StmtPrinter::VisitContinueStmt(ContinueStmt *Node) { - Indent() << "continue;\n"; + Indent() << "continue;"; + if (Policy.IncludeNewlines) OS << "\n"; } void StmtPrinter::VisitBreakStmt(BreakStmt *Node) { - Indent() << "break;\n"; + Indent() << "break;"; + if (Policy.IncludeNewlines) OS << "\n"; } @@ -374,7 +366,8 @@ void StmtPrinter::VisitReturnStmt(ReturnStmt *Node) { OS << " "; PrintExpr(Node->getRetValue()); } - OS << ";\n"; + OS << ";"; + if (Policy.IncludeNewlines) OS << "\n"; } @@ -437,7 +430,8 @@ void StmtPrinter::VisitGCCAsmStmt(GCCAsmStmt *Node) { VisitStringLiteral(Node->getClobberStringLiteral(i)); } - OS << ");\n"; + OS << ");"; + if (Policy.IncludeNewlines) OS << "\n"; } void StmtPrinter::VisitMSAsmStmt(MSAsmStmt *Node) { @@ -579,6 +573,11 @@ void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) { OS << "\n"; } +void StmtPrinter::VisitSEHLeaveStmt(SEHLeaveStmt *Node) { + Indent() << "__leave;"; + if (Policy.IncludeNewlines) OS << "\n"; +} + //===----------------------------------------------------------------------===// // OpenMP clauses printing methods //===----------------------------------------------------------------------===// @@ -586,29 +585,100 @@ void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) { namespace { class OMPClausePrinter : public OMPClauseVisitor<OMPClausePrinter> { raw_ostream &OS; + const PrintingPolicy &Policy; /// \brief Process clauses with list of variables. template <typename T> void VisitOMPClauseList(T *Node, char StartSym); public: - OMPClausePrinter(raw_ostream &OS) : OS(OS) { } + OMPClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy) + : OS(OS), Policy(Policy) { } #define OPENMP_CLAUSE(Name, Class) \ void Visit##Class(Class *S); #include "clang/Basic/OpenMPKinds.def" }; +void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) { + OS << "if("; + Node->getCondition()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPFinalClause(OMPFinalClause *Node) { + OS << "final("; + Node->getCondition()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) { + OS << "num_threads("; + Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) { + OS << "safelen("; + Node->getSafelen()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) { + OS << "collapse("; + Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) { OS << "default(" << getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind()) << ")"; } +void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) { + OS << "proc_bind(" + << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, Node->getProcBindKind()) + << ")"; +} + +void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) { + OS << "schedule(" + << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind()); + if (Node->getChunkSize()) { + OS << ", "; + Node->getChunkSize()->printPretty(OS, nullptr, Policy); + } + OS << ")"; +} + +void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *) { + OS << "ordered"; +} + +void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) { + OS << "nowait"; +} + +void OMPClausePrinter::VisitOMPUntiedClause(OMPUntiedClause *) { + OS << "untied"; +} + +void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) { + OS << "mergeable"; +} + template<typename T> void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) { for (typename T::varlist_iterator I = Node->varlist_begin(), E = Node->varlist_end(); - I != E; ++I) - OS << (I == Node->varlist_begin() ? StartSym : ',') - << *cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl()); + I != E; ++I) { + assert(*I && "Expected non-null Stmt"); + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*I)) { + OS << (I == Node->varlist_begin() ? StartSym : ','); + cast<NamedDecl>(DRE->getDecl())->printQualifiedName(OS); + } else { + OS << (I == Node->varlist_begin() ? StartSym : ','); + (*I)->printPretty(OS, nullptr, Policy, 0); + } + } } void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) { @@ -627,6 +697,14 @@ void OMPClausePrinter::VisitOMPFirstprivateClause(OMPFirstprivateClause *Node) { } } +void OMPClausePrinter::VisitOMPLastprivateClause(OMPLastprivateClause *Node) { + if (!Node->varlist_empty()) { + OS << "lastprivate"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) { if (!Node->varlist_empty()) { OS << "shared"; @@ -635,17 +713,83 @@ void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) { } } +void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) { + if (!Node->varlist_empty()) { + OS << "reduction("; + NestedNameSpecifier *QualifierLoc = + Node->getQualifierLoc().getNestedNameSpecifier(); + OverloadedOperatorKind OOK = + Node->getNameInfo().getName().getCXXOverloadedOperator(); + if (QualifierLoc == nullptr && OOK != OO_None) { + // Print reduction identifier in C format + OS << getOperatorSpelling(OOK); + } else { + // Use C++ format + if (QualifierLoc != nullptr) + QualifierLoc->print(OS, Policy); + OS << Node->getNameInfo(); + } + OS << ":"; + VisitOMPClauseList(Node, ' '); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) { + if (!Node->varlist_empty()) { + OS << "linear"; + VisitOMPClauseList(Node, '('); + if (Node->getStep() != nullptr) { + OS << ": "; + Node->getStep()->printPretty(OS, nullptr, Policy, 0); + } + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPAlignedClause(OMPAlignedClause *Node) { + if (!Node->varlist_empty()) { + OS << "aligned"; + VisitOMPClauseList(Node, '('); + if (Node->getAlignment() != nullptr) { + OS << ": "; + Node->getAlignment()->printPretty(OS, nullptr, Policy, 0); + } + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) { + if (!Node->varlist_empty()) { + OS << "copyin"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) { + if (!Node->varlist_empty()) { + OS << "copyprivate"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) { + if (!Node->varlist_empty()) { + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} } //===----------------------------------------------------------------------===// // OpenMP directives printing methods //===----------------------------------------------------------------------===// -void StmtPrinter::VisitOMPParallelDirective(OMPParallelDirective *Node) { - Indent() << "#pragma omp parallel "; - - OMPClausePrinter Printer(OS); - ArrayRef<OMPClause *> Clauses = Node->clauses(); +void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S) { + OMPClausePrinter Printer(OS, Policy); + ArrayRef<OMPClause *> Clauses = S->clauses(); for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end(); I != E; ++I) if (*I && !(*I)->isImplicit()) { @@ -653,13 +797,95 @@ void StmtPrinter::VisitOMPParallelDirective(OMPParallelDirective *Node) { OS << ' '; } OS << "\n"; - if (Node->getAssociatedStmt()) { - assert(isa<CapturedStmt>(Node->getAssociatedStmt()) && + if (S->hasAssociatedStmt() && S->getAssociatedStmt()) { + assert(isa<CapturedStmt>(S->getAssociatedStmt()) && "Expected captured statement!"); - Stmt *CS = cast<CapturedStmt>(Node->getAssociatedStmt())->getCapturedStmt(); + Stmt *CS = cast<CapturedStmt>(S->getAssociatedStmt())->getCapturedStmt(); PrintStmt(CS); } } + +void StmtPrinter::VisitOMPParallelDirective(OMPParallelDirective *Node) { + Indent() << "#pragma omp parallel "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPSimdDirective(OMPSimdDirective *Node) { + Indent() << "#pragma omp simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) { + Indent() << "#pragma omp for "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPSectionsDirective(OMPSectionsDirective *Node) { + Indent() << "#pragma omp sections "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPSectionDirective(OMPSectionDirective *Node) { + Indent() << "#pragma omp section"; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPSingleDirective(OMPSingleDirective *Node) { + Indent() << "#pragma omp single "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPMasterDirective(OMPMasterDirective *Node) { + Indent() << "#pragma omp master"; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPCriticalDirective(OMPCriticalDirective *Node) { + Indent() << "#pragma omp critical"; + if (Node->getDirectiveName().getName()) { + OS << " ("; + Node->getDirectiveName().printName(OS); + OS << ")"; + } + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPParallelForDirective(OMPParallelForDirective *Node) { + Indent() << "#pragma omp parallel for "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPParallelSectionsDirective( + OMPParallelSectionsDirective *Node) { + Indent() << "#pragma omp parallel sections "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTaskDirective(OMPTaskDirective *Node) { + Indent() << "#pragma omp task "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *Node) { + Indent() << "#pragma omp taskyield"; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPBarrierDirective(OMPBarrierDirective *Node) { + Indent() << "#pragma omp barrier"; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) { + Indent() << "#pragma omp taskwait"; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) { + Indent() << "#pragma omp flush "; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// @@ -717,7 +943,7 @@ void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { } if (Node->isImplicitProperty()) - OS << Node->getImplicitPropertyGetter()->getSelector().getAsString(); + Node->getImplicitPropertyGetter()->getSelector().print(OS); else OS << Node->getExplicitProperty()->getName(); } @@ -743,6 +969,9 @@ void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) { case PredefinedExpr::FuncDName: OS << "__FUNCDNAME__"; break; + case PredefinedExpr::FuncSig: + OS << "__FUNCSIG__"; + break; case PredefinedExpr::LFunction: OS << "L__FUNCTION__"; break; @@ -814,11 +1043,10 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { // Emit suffixes. Integer literals are always a builtin integer type. switch (Node->getType()->getAs<BuiltinType>()->getKind()) { default: llvm_unreachable("Unexpected type for integer literal!"); - // FIXME: The Short and UShort cases are to handle cases where a short - // integeral literal is formed during template instantiation. They should - // be removed when template instantiation no longer needs integer literals. - case BuiltinType::Short: - case BuiltinType::UShort: + case BuiltinType::SChar: OS << "i8"; break; + case BuiltinType::UChar: OS << "Ui8"; break; + case BuiltinType::Short: OS << "i16"; break; + case BuiltinType::UShort: OS << "Ui16"; break; case BuiltinType::Int: break; // no suffix. case BuiltinType::UInt: OS << 'U'; break; case BuiltinType::Long: OS << 'L'; break; @@ -1002,7 +1230,7 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) { MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase()); FieldDecl *ParentDecl = ParentMember - ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) : NULL; + ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) : nullptr; if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion()) OS << (Node->isArrow() ? "->" : "."); @@ -1043,7 +1271,7 @@ void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) { PrintExpr(Node->getInitializer()); } void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) { - // No need to print anything, simply forward to the sub expression. + // No need to print anything, simply forward to the subexpression. PrintExpr(Node->getSubExpr()); } void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) { @@ -1144,10 +1372,12 @@ void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) { DEnd = Node->designators_end(); D != DEnd; ++D) { if (D->isFieldDesignator()) { - if (D->getDotLoc().isInvalid()) - OS << D->getFieldName()->getName() << ":"; - else + if (D->getDotLoc().isInvalid()) { + if (IdentifierInfo *II = D->getFieldName()) + OS << II->getName() << ":"; + } else { OS << "." << D->getFieldName()->getName(); + } } else { OS << "["; if (D->isArrayDesignator()) { @@ -1194,7 +1424,7 @@ void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) { } void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) { - const char *Name = 0; + const char *Name = nullptr; switch (Node->getOp()) { #define BUILTIN(ID, TYPE, ATTRS) #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ @@ -1281,6 +1511,12 @@ void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) { } void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) { + // If we have a conversion operator call only print the argument. + CXXMethodDecl *MD = Node->getMethodDecl(); + if (MD && isa<CXXConversionDecl>(MD)) { + PrintExpr(Node->getImplicitObjectArgument()); + return; + } VisitCallExpr(cast<CallExpr>(Node)); } @@ -1360,9 +1596,8 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { cast<FunctionDecl>(DRE->getDecl())->getTemplateSpecializationArgs(); assert(Args); const TemplateArgument &Pack = Args->get(0); - for (TemplateArgument::pack_iterator I = Pack.pack_begin(), - E = Pack.pack_end(); I != E; ++I) { - char C = (char)I->getAsIntegral().getZExtValue(); + for (const auto &P : Pack.pack_elements()) { + char C = (char)P.getAsIntegral().getZExtValue(); OS << C; } break; @@ -1400,7 +1635,7 @@ void StmtPrinter::VisitCXXThisExpr(CXXThisExpr *Node) { } void StmtPrinter::VisitCXXThrowExpr(CXXThrowExpr *Node) { - if (Node->getSubExpr() == 0) + if (!Node->getSubExpr()) OS << "throw"; else { OS << "throw "; @@ -1492,16 +1727,14 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { OS << " ("; CXXMethodDecl *Method = Node->getCallOperator(); NeedComma = false; - for (CXXMethodDecl::param_iterator P = Method->param_begin(), - PEnd = Method->param_end(); - P != PEnd; ++P) { + for (auto P : Method->params()) { if (NeedComma) { OS << ", "; } else { NeedComma = true; } - std::string ParamStr = (*P)->getNameAsString(); - (*P)->getOriginalType().print(OS, Policy, ParamStr); + std::string ParamStr = P->getNameAsString(); + P->getOriginalType().print(OS, Policy, ParamStr); } if (Method->isVariadic()) { if (NeedComma) @@ -1522,7 +1755,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { // Print the trailing return type if it was specified in the source. if (Node->hasExplicitResultType()) { OS << " -> "; - Proto->getResultType().print(OS, Policy); + Proto->getReturnType().print(OS, Policy); } } @@ -1627,7 +1860,7 @@ void StmtPrinter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { } void StmtPrinter::VisitExprWithCleanups(ExprWithCleanups *E) { - // Just forward to the sub expression. + // Just forward to the subexpression. PrintExpr(E->getSubExpr()); } @@ -1677,74 +1910,15 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); } -static const char *getTypeTraitName(UnaryTypeTrait UTT) { - switch (UTT) { - case UTT_HasNothrowAssign: return "__has_nothrow_assign"; - case UTT_HasNothrowMoveAssign: return "__has_nothrow_move_assign"; - case UTT_HasNothrowConstructor: return "__has_nothrow_constructor"; - case UTT_HasNothrowCopy: return "__has_nothrow_copy"; - case UTT_HasTrivialAssign: return "__has_trivial_assign"; - case UTT_HasTrivialMoveAssign: return "__has_trivial_move_assign"; - case UTT_HasTrivialMoveConstructor: return "__has_trivial_move_constructor"; - case UTT_HasTrivialDefaultConstructor: return "__has_trivial_constructor"; - case UTT_HasTrivialCopy: return "__has_trivial_copy"; - case UTT_HasTrivialDestructor: return "__has_trivial_destructor"; - case UTT_HasVirtualDestructor: return "__has_virtual_destructor"; - case UTT_IsAbstract: return "__is_abstract"; - case UTT_IsArithmetic: return "__is_arithmetic"; - case UTT_IsArray: return "__is_array"; - case UTT_IsClass: return "__is_class"; - case UTT_IsCompleteType: return "__is_complete_type"; - case UTT_IsCompound: return "__is_compound"; - case UTT_IsConst: return "__is_const"; - case UTT_IsEmpty: return "__is_empty"; - case UTT_IsEnum: return "__is_enum"; - case UTT_IsFinal: return "__is_final"; - case UTT_IsFloatingPoint: return "__is_floating_point"; - case UTT_IsFunction: return "__is_function"; - case UTT_IsFundamental: return "__is_fundamental"; - case UTT_IsIntegral: return "__is_integral"; - case UTT_IsInterfaceClass: return "__is_interface_class"; - case UTT_IsLiteral: return "__is_literal"; - case UTT_IsLvalueReference: return "__is_lvalue_reference"; - case UTT_IsMemberFunctionPointer: return "__is_member_function_pointer"; - case UTT_IsMemberObjectPointer: return "__is_member_object_pointer"; - case UTT_IsMemberPointer: return "__is_member_pointer"; - case UTT_IsObject: return "__is_object"; - case UTT_IsPOD: return "__is_pod"; - case UTT_IsPointer: return "__is_pointer"; - case UTT_IsPolymorphic: return "__is_polymorphic"; - case UTT_IsReference: return "__is_reference"; - case UTT_IsRvalueReference: return "__is_rvalue_reference"; - case UTT_IsScalar: return "__is_scalar"; - case UTT_IsSealed: return "__is_sealed"; - case UTT_IsSigned: return "__is_signed"; - case UTT_IsStandardLayout: return "__is_standard_layout"; - case UTT_IsTrivial: return "__is_trivial"; - case UTT_IsTriviallyCopyable: return "__is_trivially_copyable"; - case UTT_IsUnion: return "__is_union"; - case UTT_IsUnsigned: return "__is_unsigned"; - case UTT_IsVoid: return "__is_void"; - case UTT_IsVolatile: return "__is_volatile"; - } - llvm_unreachable("Type trait not covered by switch statement"); -} - -static const char *getTypeTraitName(BinaryTypeTrait BTT) { - switch (BTT) { - case BTT_IsBaseOf: return "__is_base_of"; - case BTT_IsConvertible: return "__is_convertible"; - case BTT_IsSame: return "__is_same"; - case BTT_TypeCompatible: return "__builtin_types_compatible_p"; - case BTT_IsConvertibleTo: return "__is_convertible_to"; - case BTT_IsTriviallyAssignable: return "__is_trivially_assignable"; - } - llvm_unreachable("Binary type trait not covered by switch"); -} - static const char *getTypeTraitName(TypeTrait TT) { switch (TT) { - case clang::TT_IsTriviallyConstructible:return "__is_trivially_constructible"; +#define TYPE_TRAIT_1(Spelling, Name, Key) \ +case clang::UTT_##Name: return #Spelling; +#define TYPE_TRAIT_2(Spelling, Name, Key) \ +case clang::BTT_##Name: return #Spelling; +#define TYPE_TRAIT_N(Spelling, Name, Key) \ + case clang::TT_##Name: return #Spelling; +#include "clang/Basic/TokenKinds.def" } llvm_unreachable("Type trait not covered by switch"); } @@ -1765,20 +1939,6 @@ static const char *getExpressionTraitName(ExpressionTrait ET) { llvm_unreachable("Expression type trait not covered by switch"); } -void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { - OS << getTypeTraitName(E->getTrait()) << '('; - E->getQueriedType().print(OS, Policy); - OS << ')'; -} - -void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { - OS << getTypeTraitName(E->getTrait()) << '('; - E->getLhsType().print(OS, Policy); - OS << ','; - E->getRhsType().print(OS, Policy); - OS << ')'; -} - void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) { OS << getTypeTraitName(E->getTrait()) << "("; for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { @@ -1883,7 +2043,9 @@ void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { } void StmtPrinter::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { - OS << "@selector(" << Node->getSelector().getAsString() << ')'; + OS << "@selector("; + Node->getSelector().print(OS); + OS << ')'; } void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { @@ -1989,18 +2151,13 @@ void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) { //===----------------------------------------------------------------------===// void Stmt::dumpPretty(const ASTContext &Context) const { - printPretty(llvm::errs(), 0, PrintingPolicy(Context.getLangOpts())); + printPretty(llvm::errs(), nullptr, PrintingPolicy(Context.getLangOpts())); } void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation) const { - if (this == 0) { - OS << "<NULL>"; - return; - } - StmtPrinter P(OS, Helper, Policy, Indentation); P.Visit(const_cast<Stmt*>(this)); } diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index 6805e62..f44f25c 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -79,9 +79,8 @@ void StmtProfiler::VisitStmt(const Stmt *S) { void StmtProfiler::VisitDeclStmt(const DeclStmt *S) { VisitStmt(S); - for (DeclStmt::const_decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); - D != DEnd; ++D) - VisitDecl(*D); + for (const auto *D : S->decls()) + VisitDecl(D); } void StmtProfiler::VisitNullStmt(const NullStmt *S) { @@ -215,6 +214,10 @@ void StmtProfiler::VisitSEHExceptStmt(const SEHExceptStmt *S) { VisitStmt(S); } +void StmtProfiler::VisitSEHLeaveStmt(const SEHLeaveStmt *S) { + VisitStmt(S); +} + void StmtProfiler::VisitCapturedStmt(const CapturedStmt *S) { VisitStmt(S); } @@ -265,14 +268,52 @@ public: #include "clang/Basic/OpenMPKinds.def" }; +void OMPClauseProfiler::VisitOMPIfClause(const OMPIfClause *C) { + if (C->getCondition()) + Profiler->VisitStmt(C->getCondition()); +} + +void OMPClauseProfiler::VisitOMPFinalClause(const OMPFinalClause *C) { + if (C->getCondition()) + Profiler->VisitStmt(C->getCondition()); +} + +void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) { + if (C->getNumThreads()) + Profiler->VisitStmt(C->getNumThreads()); +} + +void OMPClauseProfiler::VisitOMPSafelenClause(const OMPSafelenClause *C) { + if (C->getSafelen()) + Profiler->VisitStmt(C->getSafelen()); +} + +void OMPClauseProfiler::VisitOMPCollapseClause(const OMPCollapseClause *C) { + if (C->getNumForLoops()) + Profiler->VisitStmt(C->getNumForLoops()); +} + void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { } +void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { } + +void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) { + if (C->getChunkSize()) + Profiler->VisitStmt(C->getChunkSize()); +} + +void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *) {} + +void OMPClauseProfiler::VisitOMPNowaitClause(const OMPNowaitClause *) {} + +void OMPClauseProfiler::VisitOMPUntiedClause(const OMPUntiedClause *) {} + +void OMPClauseProfiler::VisitOMPMergeableClause(const OMPMergeableClause *) {} + template<typename T> void OMPClauseProfiler::VisitOMPClauseList(T *Node) { - for (typename T::varlist_const_iterator I = Node->varlist_begin(), - E = Node->varlist_end(); - I != E; ++I) - Profiler->VisitStmt(*I); + for (auto *I : Node->varlists()) + Profiler->VisitStmt(I); } void OMPClauseProfiler::VisitOMPPrivateClause(const OMPPrivateClause *C) { @@ -282,13 +323,42 @@ void OMPClauseProfiler::VisitOMPFirstprivateClause( const OMPFirstprivateClause *C) { VisitOMPClauseList(C); } +void +OMPClauseProfiler::VisitOMPLastprivateClause(const OMPLastprivateClause *C) { + VisitOMPClauseList(C); +} void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) { VisitOMPClauseList(C); } +void OMPClauseProfiler::VisitOMPReductionClause( + const OMPReductionClause *C) { + Profiler->VisitNestedNameSpecifier( + C->getQualifierLoc().getNestedNameSpecifier()); + Profiler->VisitName(C->getNameInfo().getName()); + VisitOMPClauseList(C); +} +void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) { + VisitOMPClauseList(C); + Profiler->VisitStmt(C->getStep()); +} +void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) { + VisitOMPClauseList(C); + Profiler->VisitStmt(C->getAlignment()); +} +void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) { + VisitOMPClauseList(C); +} +void +OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) { + VisitOMPClauseList(C); +} +void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) { + VisitOMPClauseList(C); +} } void -StmtProfiler::VisitOMPParallelDirective(const OMPParallelDirective *S) { +StmtProfiler::VisitOMPExecutableDirective(const OMPExecutableDirective *S) { VisitStmt(S); OMPClauseProfiler P(this); ArrayRef<OMPClause *> Clauses = S->clauses(); @@ -298,6 +368,69 @@ StmtProfiler::VisitOMPParallelDirective(const OMPParallelDirective *S) { P.Visit(*I); } +void StmtProfiler::VisitOMPParallelDirective(const OMPParallelDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPSimdDirective(const OMPSimdDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPForDirective(const OMPForDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPSectionsDirective(const OMPSectionsDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPSectionDirective(const OMPSectionDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPSingleDirective(const OMPSingleDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPMasterDirective(const OMPMasterDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPCriticalDirective(const OMPCriticalDirective *S) { + VisitOMPExecutableDirective(S); + VisitName(S->getDirectiveName().getName()); +} + +void +StmtProfiler::VisitOMPParallelForDirective(const OMPParallelForDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPParallelSectionsDirective( + const OMPParallelSectionsDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPTaskDirective(const OMPTaskDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPBarrierDirective(const OMPBarrierDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } @@ -529,7 +662,7 @@ void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) { for (unsigned i = 0; i != S->getNumAssocs(); ++i) { QualType T = S->getAssocType(i); if (T.isNull()) - ID.AddPointer(0); + ID.AddPointer(nullptr); else VisitType(T); VisitExpr(S->getAssocExpr(i)); @@ -585,11 +718,11 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, case OO_Star: if (S->getNumArgs() == 1) { - UnaryOp = UO_Minus; + UnaryOp = UO_Deref; return Stmt::UnaryOperatorClass; } - BinaryOp = BO_Sub; + BinaryOp = BO_Mul; return Stmt::BinaryOperatorClass; case OO_Slash: @@ -734,7 +867,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, llvm_unreachable("Invalid overloaded operator expression"); } - + void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { if (S->isTypeDependent()) { @@ -743,7 +876,7 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { UnaryOperatorKind UnaryOp = UO_Extension; BinaryOperatorKind BinaryOp = BO_Comma; Stmt::StmtClass SC = DecodeOperatorCall(S, UnaryOp, BinaryOp); - + ID.AddInteger(SC); for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) Visit(S->getArg(I)); @@ -754,10 +887,10 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { ID.AddInteger(BinaryOp); else assert(SC == Stmt::ArraySubscriptExprClass); - + return; } - + VisitCallExpr(S); ID.AddInteger(S->getOperator()); } @@ -923,10 +1056,10 @@ StmtProfiler::VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *S) { VisitExpr(S); ID.AddBoolean(S->isArrow()); VisitNestedNameSpecifier(S->getQualifier()); - ID.AddBoolean(S->getScopeTypeInfo() != 0); + ID.AddBoolean(S->getScopeTypeInfo() != nullptr); if (S->getScopeTypeInfo()) VisitType(S->getScopeTypeInfo()->getType()); - ID.AddBoolean(S->getDestroyedTypeInfo() != 0); + ID.AddBoolean(S->getDestroyedTypeInfo() != nullptr); if (S->getDestroyedTypeInfo()) VisitType(S->getDestroyedType()); else @@ -948,19 +1081,6 @@ StmtProfiler::VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *S) { VisitOverloadExpr(S); } -void StmtProfiler::VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *S) { - VisitExpr(S); - ID.AddInteger(S->getTrait()); - VisitType(S->getQueriedType()); -} - -void StmtProfiler::VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *S) { - VisitExpr(S); - ID.AddInteger(S->getTrait()); - VisitType(S->getLhsType()); - VisitType(S->getRhsType()); -} - void StmtProfiler::VisitTypeTraitExpr(const TypeTraitExpr *S) { VisitExpr(S); ID.AddInteger(S->getTrait()); @@ -1200,7 +1320,7 @@ void StmtProfiler::VisitDecl(const Decl *D) { } } - ID.AddPointer(D? D->getCanonicalDecl() : 0); + ID.AddPointer(D? D->getCanonicalDecl() : nullptr); } void StmtProfiler::VisitType(QualType T) { @@ -1268,9 +1388,8 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { break; case TemplateArgument::Pack: - const TemplateArgument *Pack = Arg.pack_begin(); - for (unsigned i = 0, e = Arg.pack_size(); i != e; ++i) - VisitTemplateArgument(Pack[i]); + for (const auto &P : Arg.pack_elements()) + VisitTemplateArgument(P); break; } } diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index 16efb79..ac6a754 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -114,11 +114,9 @@ bool TemplateArgument::isDependent() const { return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent()); case Pack: - for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) { - if (P->isDependent()) + for (const auto &P : pack_elements()) + if (P.isDependent()) return true; - } - return false; } @@ -155,11 +153,9 @@ bool TemplateArgument::isInstantiationDependent() const { return getAsExpr()->isInstantiationDependent(); case Pack: - for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) { - if (P->isInstantiationDependent()) + for (const auto &P : pack_elements()) + if (P.isInstantiationDependent()) return true; - } - return false; } @@ -214,8 +210,8 @@ bool TemplateArgument::containsUnexpandedParameterPack() const { break; case Pack: - for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) - if (P->containsUnexpandedParameterPack()) + for (const auto &P : pack_elements()) + if (P.containsUnexpandedParameterPack()) return true; break; @@ -248,7 +244,7 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, break; case Declaration: - ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); + ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr); break; case Template: @@ -345,7 +341,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out) const { switch (getKind()) { case Null: - Out << "<no value>"; + Out << "(no value)"; break; case Type: { @@ -362,7 +358,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy, // FIXME: distinguish between pointer and reference args? ND->printQualifiedName(Out); } else { - Out << "<anonymous>"; + Out << "(anonymous)"; } break; } @@ -386,20 +382,19 @@ void TemplateArgument::print(const PrintingPolicy &Policy, } case Expression: - getAsExpr()->printPretty(Out, 0, Policy); + getAsExpr()->printPretty(Out, nullptr, Policy); break; case Pack: Out << "<"; bool First = true; - for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end(); - P != PEnd; ++P) { + for (const auto &P : pack_elements()) { if (First) First = false; else Out << ", "; - P->print(Policy, Out); + P.print(Policy, Out); } Out << ">"; break; @@ -489,7 +484,7 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, LangOptions LangOpts; LangOpts.CPlusPlus = true; PrintingPolicy Policy(LangOpts); - Arg.getAsExpr()->printPretty(OS, 0, Policy); + Arg.getAsExpr()->printPretty(OS, nullptr, Policy); return DB << OS.str(); } @@ -511,6 +506,8 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, const ASTTemplateArgumentListInfo * ASTTemplateArgumentListInfo::Create(ASTContext &C, const TemplateArgumentListInfo &List) { + assert(llvm::alignOf<ASTTemplateArgumentListInfo>() >= + llvm::alignOf<TemplateArgumentLoc>()); std::size_t size = ASTTemplateArgumentListInfo::sizeFor(List.size()); void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>()); ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo(); diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp index 8767c63..77c8fd5 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp @@ -78,7 +78,7 @@ TemplateDecl *TemplateName::getAsTemplateDecl() const { if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) return sub->getReplacement().getAsTemplateDecl(); - return 0; + return nullptr; } bool TemplateName::isDependent() const { @@ -121,7 +121,7 @@ bool TemplateName::containsUnexpandedParameterPack() const { return DTN->getQualifier() && DTN->getQualifier()->containsUnexpandedParameterPack(); - return getAsSubstTemplateTemplateParmPack() != 0; + return getAsSubstTemplateTemplateParmPack() != nullptr; } void diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index 7421bae..1677874 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -45,7 +45,7 @@ bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const { const IdentifierInfo* QualType::getBaseTypeIdentifier() const { const Type* ty = getTypePtr(); - NamedDecl *ND = NULL; + NamedDecl *ND = nullptr; if (ty->isPointerType() || ty->isReferenceType()) return ty->getPointeeType().getBaseTypeIdentifier(); else if (ty->isRecordType()) @@ -60,7 +60,7 @@ const IdentifierInfo* QualType::getBaseTypeIdentifier() const { if (ND) return ND->getIdentifier(); - return NULL; + return nullptr; } bool QualType::isConstant(QualType T, ASTContext &Ctx) { @@ -202,7 +202,7 @@ const Type *Type::getArrayElementTypeNoTypeQual() const { // If the canonical form of this type isn't the right kind, reject it. if (!isa<ArrayType>(CanonicalType)) - return 0; + return nullptr; // If this is a typedef for an array type, strip the typedef off without // losing all typedef information. @@ -410,7 +410,7 @@ const ComplexType *Type::getAsComplexIntegerType() const { if (const ComplexType *Complex = getAs<ComplexType>()) if (Complex->getElementType()->isIntegerType()) return Complex; - return 0; + return nullptr; } QualType Type::getPointeeType() const { @@ -422,6 +422,10 @@ QualType Type::getPointeeType() const { return BPT->getPointeeType(); if (const ReferenceType *RT = getAs<ReferenceType>()) return RT->getPointeeType(); + if (const MemberPointerType *MPT = getAs<MemberPointerType>()) + return MPT->getPointeeType(); + if (const DecayedType *DT = getAs<DecayedType>()) + return DT->getPointeeType(); return QualType(); } @@ -435,13 +439,13 @@ const RecordType *Type::getAsStructureType() const { // If the canonical form of this type isn't the right kind, reject it. if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) { if (!RT->getDecl()->isStruct()) - return 0; + return nullptr; // If this is a typedef for a structure type, strip the typedef off without // losing all typedef information. return cast<RecordType>(getUnqualifiedDesugaredType()); } - return 0; + return nullptr; } const RecordType *Type::getAsUnionType() const { @@ -454,14 +458,14 @@ const RecordType *Type::getAsUnionType() const { // If the canonical form of this type isn't the right kind, reject it. if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) { if (!RT->getDecl()->isUnion()) - return 0; + return nullptr; // If this is a typedef for a union type, strip the typedef off without // losing all typedef information. return cast<RecordType>(getUnqualifiedDesugaredType()); } - return 0; + return nullptr; } ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, @@ -485,11 +489,11 @@ const ObjCObjectType *Type::getAsObjCQualifiedInterfaceType() const { if (const ObjCObjectType *T = getAs<ObjCObjectType>()) if (T->getNumProtocols() && T->getInterface()) return T; - return 0; + return nullptr; } bool Type::isObjCQualifiedInterfaceType() const { - return getAsObjCQualifiedInterfaceType() != 0; + return getAsObjCQualifiedInterfaceType() != nullptr; } const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const { @@ -499,7 +503,7 @@ const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const { if (OPT->isObjCQualifiedIdType()) return OPT; } - return 0; + return nullptr; } const ObjCObjectPointerType *Type::getAsObjCQualifiedClassType() const { @@ -509,7 +513,7 @@ const ObjCObjectPointerType *Type::getAsObjCQualifiedClassType() const { if (OPT->isObjCQualifiedClassType()) return OPT; } - return 0; + return nullptr; } const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const { @@ -517,7 +521,7 @@ const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const { if (OPT->getInterfaceType()) return OPT; } - return 0; + return nullptr; } const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const { @@ -527,12 +531,12 @@ const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const { else if (const ReferenceType *RT = getAs<ReferenceType>()) PointeeType = RT->getPointeeType(); else - return 0; + return nullptr; if (const RecordType *RT = PointeeType->getAs<RecordType>()) return dyn_cast<CXXRecordDecl>(RT->getDecl()); - return 0; + return nullptr; } CXXRecordDecl *Type::getAsCXXRecordDecl() const { @@ -541,8 +545,8 @@ CXXRecordDecl *Type::getAsCXXRecordDecl() const { else if (const InjectedClassNameType *Injected = getAs<InjectedClassNameType>()) return Injected->getDecl(); - - return 0; + + return nullptr; } namespace { @@ -552,7 +556,7 @@ namespace { using TypeVisitor<GetContainedAutoVisitor, AutoType*>::Visit; AutoType *Visit(QualType T) { if (T.isNull()) - return 0; + return nullptr; return Visit(T.getTypePtr()); } @@ -585,7 +589,7 @@ namespace { return Visit(T->getElementType()); } AutoType *VisitFunctionType(const FunctionType *T) { - return Visit(T->getResultType()); + return Visit(T->getReturnType()); } AutoType *VisitParenType(const ParenType *T) { return Visit(T->getInnerType()); @@ -593,6 +597,9 @@ namespace { AutoType *VisitAttributedType(const AttributedType *T) { return Visit(T->getModifiedType()); } + AutoType *VisitAdjustedType(const AdjustedType *T) { + return Visit(T->getOriginalType()); + } }; } @@ -688,7 +695,7 @@ bool Type::isChar32Type() const { /// types. bool Type::isAnyCharacterType() const { const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType); - if (BT == 0) return false; + if (!BT) return false; switch (BT->getKind()) { default: return false; case BuiltinType::Char_U: @@ -894,8 +901,8 @@ bool Type::isConstantSizeType() const { /// determine its size. bool Type::isIncompleteType(NamedDecl **Def) const { if (Def) - *Def = 0; - + *Def = nullptr; + switch (CanonicalType->getTypeClass()) { default: return false; case Builtin: @@ -1424,8 +1431,7 @@ TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) { llvm_unreachable("Unknown elaborated type keyword."); } -const char* -TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { +StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { switch (Keyword) { case ETK_None: return ""; case ETK_Typename: return "typename"; @@ -1516,7 +1522,7 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { case ULong: return "unsigned long"; case ULongLong: return "unsigned long long"; case UInt128: return "unsigned __int128"; - case Half: return "half"; + case Half: return Policy.Half ? "half" : "__fp16"; case Float: return "float"; case Double: return "double"; case LongDouble: return "long double"; @@ -1582,41 +1588,38 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { llvm_unreachable("Invalid calling convention."); } -FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> args, +FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, QualType canonical, const ExtProtoInfo &epi) - : FunctionType(FunctionProto, result, epi.TypeQuals, - canonical, - result->isDependentType(), - result->isInstantiationDependentType(), - result->isVariablyModifiedType(), - result->containsUnexpandedParameterPack(), - epi.ExtInfo), - NumArgs(args.size()), NumExceptions(epi.NumExceptions), - ExceptionSpecType(epi.ExceptionSpecType), - HasAnyConsumedArgs(epi.ConsumedArguments != 0), - Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn), - RefQualifier(epi.RefQualifier) -{ - assert(NumArgs == args.size() && "function has too many parameters"); + : FunctionType(FunctionProto, result, epi.TypeQuals, canonical, + result->isDependentType(), + result->isInstantiationDependentType(), + result->isVariablyModifiedType(), + result->containsUnexpandedParameterPack(), epi.ExtInfo), + NumParams(params.size()), NumExceptions(epi.NumExceptions), + ExceptionSpecType(epi.ExceptionSpecType), + HasAnyConsumedParams(epi.ConsumedParameters != nullptr), + Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn), + RefQualifier(epi.RefQualifier) { + assert(NumParams == params.size() && "function has too many parameters"); // Fill in the trailing argument array. QualType *argSlot = reinterpret_cast<QualType*>(this+1); - for (unsigned i = 0; i != NumArgs; ++i) { - if (args[i]->isDependentType()) + for (unsigned i = 0; i != NumParams; ++i) { + if (params[i]->isDependentType()) setDependent(); - else if (args[i]->isInstantiationDependentType()) + else if (params[i]->isInstantiationDependentType()) setInstantiationDependent(); - - if (args[i]->containsUnexpandedParameterPack()) + + if (params[i]->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); - argSlot[i] = args[i]; + argSlot[i] = params[i]; } if (getExceptionSpecType() == EST_Dynamic) { // Fill in the exception array. - QualType *exnSlot = argSlot + NumArgs; + QualType *exnSlot = argSlot + NumParams; for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) { if (epi.Exceptions[i]->isDependentType()) setDependent(); @@ -1630,7 +1633,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> args, } } else if (getExceptionSpecType() == EST_ComputedNoexcept) { // Store the noexcept expression and context. - Expr **noexSlot = reinterpret_cast<Expr**>(argSlot + NumArgs); + Expr **noexSlot = reinterpret_cast<Expr **>(argSlot + NumParams); *noexSlot = epi.NoexceptExpr; if (epi.NoexceptExpr) { @@ -1643,7 +1646,8 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> args, } else if (getExceptionSpecType() == EST_Uninstantiated) { // Store the function decl from which we will resolve our // exception specification. - FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot + NumArgs); + FunctionDecl **slot = + reinterpret_cast<FunctionDecl **>(argSlot + NumParams); slot[0] = epi.ExceptionSpecDecl; slot[1] = epi.ExceptionSpecTemplate; // This exception specification doesn't make the type dependent, because @@ -1651,14 +1655,15 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> args, } else if (getExceptionSpecType() == EST_Unevaluated) { // Store the function decl from which we will resolve our // exception specification. - FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot + NumArgs); + FunctionDecl **slot = + reinterpret_cast<FunctionDecl **>(argSlot + NumParams); slot[0] = epi.ExceptionSpecDecl; } - if (epi.ConsumedArguments) { - bool *consumedArgs = const_cast<bool*>(getConsumedArgsBuffer()); - for (unsigned i = 0; i != NumArgs; ++i) - consumedArgs[i] = epi.ConsumedArguments[i]; + if (epi.ConsumedParameters) { + bool *consumedParams = const_cast<bool *>(getConsumedParamsBuffer()); + for (unsigned i = 0; i != NumParams; ++i) + consumedParams[i] = epi.ConsumedParameters[i]; } } @@ -1678,7 +1683,7 @@ FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const { return NR_Dependent; llvm::APSInt value; - bool isICE = noexceptExpr->isIntegerConstantExpr(value, ctx, 0, + bool isICE = noexceptExpr->isIntegerConstantExpr(value, ctx, nullptr, /*evaluated*/false); (void)isICE; assert(isICE && "AST should not contain bad noexcept expressions."); @@ -1686,16 +1691,41 @@ FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const { return value.getBoolValue() ? NR_Nothrow : NR_Throw; } +bool FunctionProtoType::isNothrow(const ASTContext &Ctx, + bool ResultIfDependent) const { + ExceptionSpecificationType EST = getExceptionSpecType(); + assert(EST != EST_Unevaluated && EST != EST_Uninstantiated); + if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) + return true; + + if (EST == EST_Dynamic && ResultIfDependent == true) { + // A dynamic exception specification is throwing unless every exception + // type is an (unexpanded) pack expansion type. + for (unsigned I = 0, N = NumExceptions; I != N; ++I) + if (!getExceptionType(I)->getAs<PackExpansionType>()) + return false; + return ResultIfDependent; + } + + if (EST != EST_ComputedNoexcept) + return false; + + NoexceptResult NR = getNoexceptSpec(Ctx); + if (NR == NR_Dependent) + return ResultIfDependent; + return NR == NR_Nothrow; +} + bool FunctionProtoType::isTemplateVariadic() const { - for (unsigned ArgIdx = getNumArgs(); ArgIdx; --ArgIdx) - if (isa<PackExpansionType>(getArgType(ArgIdx - 1))) + for (unsigned ArgIdx = getNumParams(); ArgIdx; --ArgIdx) + if (isa<PackExpansionType>(getParamType(ArgIdx - 1))) return true; return false; } void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, - const QualType *ArgTys, unsigned NumArgs, + const QualType *ArgTys, unsigned NumParams, const ExtProtoInfo &epi, const ASTContext &Context) { @@ -1717,7 +1747,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, // whether the following bool is the EH spec or part of the arguments. ID.AddPointer(Result.getAsOpaquePtr()); - for (unsigned i = 0; i != NumArgs; ++i) + for (unsigned i = 0; i != NumParams; ++i) ID.AddPointer(ArgTys[i].getAsOpaquePtr()); // This method is relatively performance sensitive, so as a performance // shortcut, use one AddInteger call instead of four for the next four @@ -1740,9 +1770,9 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, epi.ExceptionSpecType == EST_Unevaluated) { ID.AddPointer(epi.ExceptionSpecDecl->getCanonicalDecl()); } - if (epi.ConsumedArguments) { - for (unsigned i = 0; i != NumArgs; ++i) - ID.AddBoolean(epi.ConsumedArguments[i]); + if (epi.ConsumedParameters) { + for (unsigned i = 0; i != NumParams; ++i) + ID.AddBoolean(epi.ConsumedParameters[i]); } epi.ExtInfo.Profile(ID); ID.AddBoolean(epi.HasTrailingReturn); @@ -1750,7 +1780,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { - Profile(ID, getResultType(), arg_type_begin(), NumArgs, getExtProtoInfo(), + Profile(ID, getReturnType(), param_type_begin(), NumParams, getExtProtoInfo(), Ctx); } @@ -1819,11 +1849,9 @@ TagType::TagType(TypeClass TC, const TagDecl *D, QualType can) decl(const_cast<TagDecl*>(D)) {} static TagDecl *getInterestingTagDecl(TagDecl *decl) { - for (TagDecl::redecl_iterator I = decl->redecls_begin(), - E = decl->redecls_end(); - I != E; ++I) { + for (auto I : decl->redecls()) { if (I->isCompleteDefinition() || I->isBeingDefined()) - return *I; + return I; } // If there's no definition (not even in progress), return what we have. return decl; @@ -1896,7 +1924,7 @@ CXXRecordDecl *InjectedClassNameType::getDecl() const { } IdentifierInfo *TemplateTypeParmType::getIdentifier() const { - return isCanonicalUnqualified() ? 0 : getDecl()->getIdentifier(); + return isCanonicalUnqualified() ? nullptr : getDecl()->getIdentifier(); } SubstTemplateTypeParmPackType:: @@ -1922,10 +1950,8 @@ void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument &ArgPack) { ID.AddPointer(Replaced); ID.AddInteger(ArgPack.pack_size()); - for (TemplateArgument::pack_iterator P = ArgPack.pack_begin(), - PEnd = ArgPack.pack_end(); - P != PEnd; ++P) - ID.AddPointer(P->getAsType().getAsOpaquePtr()); + for (const auto &P : ArgPack.pack_elements()) + ID.AddPointer(P.getAsType().getAsOpaquePtr()); } bool TemplateSpecializationType:: @@ -2200,13 +2226,12 @@ static CachedProperties computeCachedProperties(const Type *T) { case Type::ExtVector: return Cache::get(cast<VectorType>(T)->getElementType()); case Type::FunctionNoProto: - return Cache::get(cast<FunctionType>(T)->getResultType()); + return Cache::get(cast<FunctionType>(T)->getReturnType()); case Type::FunctionProto: { const FunctionProtoType *FPT = cast<FunctionProtoType>(T); - CachedProperties result = Cache::get(FPT->getResultType()); - for (FunctionProtoType::arg_type_iterator ai = FPT->arg_type_begin(), - ae = FPT->arg_type_end(); ai != ae; ++ai) - result = merge(result, Cache::get(*ai)); + CachedProperties result = Cache::get(FPT->getReturnType()); + for (const auto &ai : FPT->param_types()) + result = merge(result, Cache::get(ai)); return result; } case Type::ObjCInterface: { @@ -2285,13 +2310,12 @@ static LinkageInfo computeLinkageInfo(const Type *T) { case Type::ExtVector: return computeLinkageInfo(cast<VectorType>(T)->getElementType()); case Type::FunctionNoProto: - return computeLinkageInfo(cast<FunctionType>(T)->getResultType()); + return computeLinkageInfo(cast<FunctionType>(T)->getReturnType()); case Type::FunctionProto: { const FunctionProtoType *FPT = cast<FunctionProtoType>(T); - LinkageInfo LV = computeLinkageInfo(FPT->getResultType()); - for (FunctionProtoType::arg_type_iterator ai = FPT->arg_type_begin(), - ae = FPT->arg_type_end(); ai != ae; ++ai) - LV.merge(computeLinkageInfo(*ai)); + LinkageInfo LV = computeLinkageInfo(FPT->getReturnType()); + for (const auto &ai : FPT->param_types()) + LV.merge(computeLinkageInfo(ai)); return LV; } case Type::ObjCInterface: @@ -2441,3 +2465,7 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { return DK_none; } + +CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { + return getClass()->getAsCXXRecordDecl()->getMostRecentDecl(); +} diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp index 22a51bc..208d695 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp @@ -55,7 +55,7 @@ namespace { /// \brief Returns the alignment of the type source info data block. unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) { if (Ty.isNull()) return 1; - return TypeAligner().Visit(TypeLoc(Ty, 0)); + return TypeAligner().Visit(TypeLoc(Ty, nullptr)); } namespace { @@ -73,7 +73,7 @@ namespace { /// \brief Returns the size of the type source info data block. unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { unsigned Total = 0; - TypeLoc TyLoc(Ty, 0); + TypeLoc TyLoc(Ty, nullptr); unsigned MaxAlign = 1; while (!TyLoc.isNull()) { unsigned Align = getLocalAlignmentForType(TyLoc.getType()); diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index 571e3db..061473e 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -204,6 +204,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, NeedARCStrongQualifier = true; // Fall through + case Type::Adjusted: case Type::Decayed: case Type::Pointer: case Type::BlockPointer: @@ -429,7 +430,16 @@ void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T, } void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T, raw_ostream &OS) { - OS << '[' << T->getSize().getZExtValue() << ']'; + OS << '['; + if (T->getIndexTypeQualifiers().hasQualifiers()) { + AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers()); + OS << ' '; + } + + if (T->getSizeModifier() == ArrayType::Static) + OS << "static "; + + OS << T->getSize().getZExtValue() << ']'; printAfter(T->getElementType(), OS); } @@ -460,23 +470,32 @@ void TypePrinter::printVariableArrayAfter(const VariableArrayType *T, } if (T->getSizeModifier() == VariableArrayType::Static) - OS << "static"; + OS << "static "; else if (T->getSizeModifier() == VariableArrayType::Star) OS << '*'; if (T->getSizeExpr()) - T->getSizeExpr()->printPretty(OS, 0, Policy); + T->getSizeExpr()->printPretty(OS, nullptr, Policy); OS << ']'; printAfter(T->getElementType(), OS); } +void TypePrinter::printAdjustedBefore(const AdjustedType *T, raw_ostream &OS) { + // Print the adjusted representation, otherwise the adjustment will be + // invisible. + printBefore(T->getAdjustedType(), OS); +} +void TypePrinter::printAdjustedAfter(const AdjustedType *T, raw_ostream &OS) { + printAfter(T->getAdjustedType(), OS); +} + void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) { // Print as though it's a pointer. - printBefore(T->getDecayedType(), OS); + printAdjustedBefore(T, OS); } void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) { - printAfter(T->getDecayedType(), OS); + printAdjustedAfter(T, OS); } void TypePrinter::printDependentSizedArrayBefore( @@ -491,7 +510,7 @@ void TypePrinter::printDependentSizedArrayAfter( raw_ostream &OS) { OS << '['; if (T->getSizeExpr()) - T->getSizeExpr()->printPretty(OS, 0, Policy); + T->getSizeExpr()->printPretty(OS, nullptr, Policy); OS << ']'; printAfter(T->getElementType(), OS); } @@ -506,7 +525,7 @@ void TypePrinter::printDependentSizedExtVectorAfter( raw_ostream &OS) { OS << " __attribute__((ext_vector_type("; if (T->getSizeExpr()) - T->getSizeExpr()->printPretty(OS, 0, Policy); + T->getSizeExpr()->printPretty(OS, nullptr, Policy); OS << ")))"; printAfter(T->getElementType(), OS); } @@ -583,7 +602,8 @@ FunctionProtoType::printExceptionSpecification(raw_ostream &OS, OS << " noexcept"; if (getExceptionSpecType() == EST_ComputedNoexcept) { OS << '('; - getNoexceptExpr()->printPretty(OS, 0, Policy); + if (getNoexceptExpr()) + getNoexceptExpr()->printPretty(OS, nullptr, Policy); OS << ')'; } } @@ -598,7 +618,7 @@ void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T, } else { // If needed for precedence reasons, wrap the inner part in grouping parens. SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false); - printBefore(T->getResultType(), OS); + printBefore(T->getReturnType(), OS); if (!PrevPHIsEmpty.get()) OS << '('; } @@ -614,17 +634,17 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, OS << '('; { ParamPolicyRAII ParamPolicy(Policy); - for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) { + for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) { if (i) OS << ", "; - print(T->getArgType(i), OS, StringRef()); + print(T->getParamType(i), OS, StringRef()); } } if (T->isVariadic()) { - if (T->getNumArgs()) + if (T->getNumParams()) OS << ", "; OS << "..."; - } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) { + } else if (T->getNumParams() == 0 && !Policy.LangOpts.CPlusPlus) { // Do not emit int() if we have a proto, emit 'int(void)'. OS << "void"; } @@ -703,17 +723,17 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, T->printExceptionSpecification(OS, Policy); if (T->hasTrailingReturn()) { - OS << " -> "; - print(T->getResultType(), OS, StringRef()); + OS << " -> "; + print(T->getReturnType(), OS, StringRef()); } else - printAfter(T->getResultType(), OS); + printAfter(T->getReturnType(), OS); } void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T, raw_ostream &OS) { // If needed for precedence reasons, wrap the inner part in grouping parens. SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false); - printBefore(T->getResultType(), OS); + printBefore(T->getReturnType(), OS); if (!PrevPHIsEmpty.get()) OS << '('; } @@ -727,7 +747,7 @@ void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T, OS << "()"; if (T->getNoReturnAttr()) OS << " __attribute__((noreturn))"; - printAfter(T->getResultType(), OS); + printAfter(T->getReturnType(), OS); } void TypePrinter::printTypeSpec(const NamedDecl *D, raw_ostream &OS) { @@ -751,7 +771,8 @@ void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) { } void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T, raw_ostream &OS) { OS << "typeof "; - T->getUnderlyingExpr()->printPretty(OS, 0, Policy); + if (T->getUnderlyingExpr()) + T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy); spaceBeforePlaceHolder(OS); } void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T, @@ -767,7 +788,8 @@ void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) { } void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) { OS << "decltype("; - T->getUnderlyingExpr()->printPretty(OS, 0, Policy); + if (T->getUnderlyingExpr()) + T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy); OS << ')'; spaceBeforePlaceHolder(OS); } @@ -838,7 +860,7 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) { if (NS->getIdentifier()) OS << NS->getName() << "::"; else - OS << "<anonymous>::"; + OS << "(anonymous namespace)::"; } else if (ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { IncludeStrongLifetimeRAII Strong(Policy); @@ -890,13 +912,13 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { OS << Typedef->getIdentifier()->getName(); } else { // Make an unambiguous representation for anonymous types, e.g. - // <anonymous enum at /usr/include/string.h:120:9> + // (anonymous enum at /usr/include/string.h:120:9) if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) { - OS << "<lambda"; + OS << "(lambda"; HasKindDecoration = true; } else { - OS << "<anonymous"; + OS << "(anonymous"; } if (Policy.AnonymousTagLocations) { @@ -915,7 +937,7 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { } } - OS << '>'; + OS << ')'; } // If this is a class template specialization, print the template @@ -1249,13 +1271,12 @@ void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T, print(T->getBaseType(), OS, StringRef()); OS << '<'; bool isFirst = true; - for (ObjCObjectType::qual_iterator - I = T->qual_begin(), E = T->qual_end(); I != E; ++I) { + for (const auto *I : T->quals()) { if (isFirst) isFirst = false; else OS << ','; - OS << (*I)->getName(); + OS << I->getName(); } OS << '>'; spaceBeforePlaceHolder(OS); @@ -1271,12 +1292,12 @@ void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T, T->getPointeeType().getLocalQualifiers().print(OS, Policy, /*appendSpaceIfNonEmpty=*/true); + assert(!T->isObjCSelType()); + if (T->isObjCIdType() || T->isObjCQualifiedIdType()) OS << "id"; else if (T->isObjCClassType() || T->isObjCQualifiedClassType()) OS << "Class"; - else if (T->isObjCSelType()) - OS << "SEL"; else OS << T->getInterfaceDecl()->getName(); @@ -1292,7 +1313,8 @@ void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T, OS << '>'; } - if (!T->isObjCIdType() && !T->isObjCQualifiedIdType()) { + if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() && + !T->isObjCClassType() && !T->isObjCQualifiedClassType()) { OS << " *"; // Don't forget the implicit pointer. } else { spaceBeforePlaceHolder(OS); @@ -1413,13 +1435,10 @@ void QualType::dump(const char *msg) const { print(llvm::errs(), PrintingPolicy(LO), "identifier"); llvm::errs() << '\n'; } -void QualType::dump() const { - dump(0); -} -void Type::dump() const { - QualType(this, 0).dump(); -} +LLVM_DUMP_METHOD void QualType::dump() const { dump(nullptr); } + +LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); } std::string Qualifiers::getAsString() const { LangOptions LO; diff --git a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp index 5ca4e86..c213d1c 100644 --- a/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp @@ -56,15 +56,13 @@ void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { const CXXRecordDecl *RD = Base.getBase(); - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - + for (const auto &I : RD->bases()) { // Don't layout virtual bases. - if (I->isVirtual()) + if (I.isVirtual()) continue; const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl()); const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); CharUnits BaseOffset = Base.getBaseOffset() + @@ -88,10 +86,9 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, if (!RD->getNumVBases() && !BaseIsMorallyVirtual) return; - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { + for (const auto &I : RD->bases()) { const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl()); // Itanium C++ ABI 2.6.2: // Secondary virtual pointers are present for all bases with either @@ -106,7 +103,7 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual; bool BaseDeclIsNonVirtualPrimaryBase = false; CharUnits BaseOffset; - if (I->isVirtual()) { + if (I.isVirtual()) { // Ignore virtual bases that we've already visited. if (!VBases.insert(BaseDecl)) continue; @@ -153,13 +150,12 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) { - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { + for (const auto &I : RD->bases()) { const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl()); // Check if this is a virtual base. - if (I->isVirtual()) { + if (I.isVirtual()) { // Check if we've seen this base before. if (!VBases.insert(BaseDecl)) continue; diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp index 5f7ae0f..fa1127f 100644 --- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp @@ -16,6 +16,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -43,9 +44,9 @@ struct BaseOffset { /// path from the derived class to the base class involves a virtual base /// class. CharUnits NonVirtualOffset; - - BaseOffset() : DerivedClass(0), VirtualBase(0), - NonVirtualOffset(CharUnits::Zero()) { } + + BaseOffset() : DerivedClass(nullptr), VirtualBase(nullptr), + NonVirtualOffset(CharUnits::Zero()) { } BaseOffset(const CXXRecordDecl *DerivedClass, const CXXRecordDecl *VirtualBase, CharUnits NonVirtualOffset) : DerivedClass(DerivedClass), VirtualBase(VirtualBase), @@ -63,10 +64,15 @@ public: /// Method - The method decl of the overrider. const CXXMethodDecl *Method; + /// VirtualBase - The virtual base class subobject of this overridder. + /// Note that this records the closest derived virtual base class subobject. + const CXXRecordDecl *VirtualBase; + /// Offset - the base offset of the overrider's parent in the layout class. CharUnits Offset; - - OverriderInfo() : Method(0), Offset(CharUnits::Zero()) { } + + OverriderInfo() : Method(nullptr), VirtualBase(nullptr), + Offset(CharUnits::Zero()) { } }; private: @@ -200,6 +206,7 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, Overrider.Offset = OverriderOffset; Overrider.Method = Method.Method; + Overrider.VirtualBase = Method.InVirtualSubobject; } } @@ -215,8 +222,8 @@ static BaseOffset ComputeBaseOffset(ASTContext &Context, CharUnits NonVirtualOffset = CharUnits::Zero(); unsigned NonVirtualStart = 0; - const CXXRecordDecl *VirtualBase = 0; - + const CXXRecordDecl *VirtualBase = nullptr; + // First, look for the virtual base class. for (int I = Path.size(), E = 0; I != E; --I) { const CXXBasePathElement &Element = Path[I - 1]; @@ -268,11 +275,11 @@ ComputeReturnAdjustmentBaseOffset(ASTContext &Context, const FunctionType *DerivedFT = DerivedMD->getType()->getAs<FunctionType>(); // Canonicalize the return types. - CanQualType CanDerivedReturnType = - Context.getCanonicalType(DerivedFT->getResultType()); - CanQualType CanBaseReturnType = - Context.getCanonicalType(BaseFT->getResultType()); - + CanQualType CanDerivedReturnType = + Context.getCanonicalType(DerivedFT->getReturnType()); + CanQualType CanBaseReturnType = + Context.getCanonicalType(BaseFT->getReturnType()); + assert(CanDerivedReturnType->getTypeClass() == CanBaseReturnType->getTypeClass() && "Types must have same type class!"); @@ -337,13 +344,12 @@ FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, OffsetInLayoutClass; // Traverse our bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl(); + for (const auto &B : RD->bases()) { + const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); CharUnits BaseOffset; CharUnits BaseOffsetInLayoutClass; - if (I->isVirtual()) { + if (B.isVirtual()) { // Check if we've visited this virtual base before. if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0))) continue; @@ -363,7 +369,7 @@ FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, } ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset), - I->isVirtual(), BaseOffsetInLayoutClass, + B.isVirtual(), BaseOffsetInLayoutClass, SubobjectOffsets, SubobjectLayoutClassOffsets, SubobjectCounts); } @@ -374,16 +380,15 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base, const CXXRecordDecl *RD = Base.getBase(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl(); + for (const auto &B : RD->bases()) { + const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); // Ignore bases that don't have any virtual member functions. if (!BaseDecl->isPolymorphic()) continue; CharUnits BaseOffset; - if (I->isVirtual()) { + if (B.isVirtual()) { if (!VisitedVirtualBases.insert(BaseDecl)) { // We've visited this base before. continue; @@ -397,21 +402,22 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base, dump(Out, BaseSubobject(BaseDecl, BaseOffset), VisitedVirtualBases); } - Out << "Final overriders for (" << RD->getQualifiedNameAsString() << ", "; + Out << "Final overriders for ("; + RD->printQualifiedName(Out); + Out << ", "; Out << Base.getBaseOffset().getQuantity() << ")\n"; // Now dump the overriders for this base subobject. - for (CXXRecordDecl::method_iterator I = RD->method_begin(), - E = RD->method_end(); I != E; ++I) { - const CXXMethodDecl *MD = *I; - + for (const auto *MD : RD->methods()) { if (!MD->isVirtual()) continue; OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset()); - Out << " " << MD->getQualifiedNameAsString() << " - ("; - Out << Overrider.Method->getQualifiedNameAsString(); + Out << " "; + MD->printQualifiedName(Out); + Out << " - ("; + Overrider.Method->printQualifiedName(Out); Out << ", " << Overrider.Offset.getQuantity() << ')'; BaseOffset Offset; @@ -420,8 +426,10 @@ void FinalOverriders::dump(raw_ostream &Out, BaseSubobject Base, if (!Offset.isEmpty()) { Out << " [ret-adj: "; - if (Offset.VirtualBase) - Out << Offset.VirtualBase->getQualifiedNameAsString() << " vbase, "; + if (Offset.VirtualBase) { + Offset.VirtualBase->printQualifiedName(Out); + Out << " vbase, "; + } Out << Offset.NonVirtualOffset.getQuantity() << " nv]"; } @@ -472,10 +480,10 @@ static bool HasSameVirtualSignature(const CXXMethodDecl *LHS, // list here because there isn't necessarily an inheritance // relationship between the two methods. if (LT->getTypeQuals() != RT->getTypeQuals() || - LT->getNumArgs() != RT->getNumArgs()) + LT->getNumParams() != RT->getNumParams()) return false; - for (unsigned I = 0, E = LT->getNumArgs(); I != E; ++I) - if (LT->getArgType(I) != RT->getArgType(I)) + for (unsigned I = 0, E = LT->getNumParams(); I != E; ++I) + if (LT->getParamType(I) != RT->getParamType(I)) return false; return true; } @@ -684,10 +692,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base, } // Add the vcall offsets. - for (CXXRecordDecl::method_iterator I = RD->method_begin(), - E = RD->method_end(); I != E; ++I) { - const CXXMethodDecl *MD = *I; - + for (const auto *MD : RD->methods()) { if (!MD->isVirtual()) continue; @@ -715,13 +720,11 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base, } // And iterate over all non-virtual bases (ignoring the primary base). - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - - if (I->isVirtual()) + for (const auto &B : RD->bases()) { + if (B.isVirtual()) continue; - const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl(); + const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); if (BaseDecl == PrimaryBase) continue; @@ -741,12 +744,11 @@ VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD, Context.getASTRecordLayout(LayoutClass); // Add vbase offsets. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl(); + for (const auto &B : RD->bases()) { + const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); // Check if this is a virtual base that we haven't visited before. - if (I->isVirtual() && VisitedVirtualBases.insert(BaseDecl)) { + if (B.isVirtual() && VisitedVirtualBases.insert(BaseDecl)) { CharUnits Offset = LayoutClassLayout.getVBaseClassOffset(BaseDecl) - OffsetInLayoutClass; @@ -1294,7 +1296,7 @@ ThisAdjustment ItaniumVTableBuilder::ComputeThisAdjustment( // We don't have vcall offsets for this virtual base, go ahead and // build them. VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass, - /*FinalOverriders=*/0, + /*FinalOverriders=*/nullptr, BaseSubobject(Offset.VirtualBase, CharUnits::Zero()), /*BaseIsVirtual=*/true, @@ -1448,8 +1450,8 @@ FindNearestOverriddenMethod(const CXXMethodDecl *MD, return OverriddenMD; } } - - return 0; + + return nullptr; } void ItaniumVTableBuilder::AddMethods( @@ -1503,16 +1505,13 @@ void ItaniumVTableBuilder::AddMethods( llvm_unreachable("Found a duplicate primary base!"); } - const CXXDestructorDecl *ImplicitVirtualDtor = 0; + const CXXDestructorDecl *ImplicitVirtualDtor = nullptr; typedef llvm::SmallVector<const CXXMethodDecl *, 8> NewVirtualFunctionsTy; NewVirtualFunctionsTy NewVirtualFunctions; // Now go through all virtual member functions and add them. - for (CXXRecordDecl::method_iterator I = RD->method_begin(), - E = RD->method_end(); I != E; ++I) { - const CXXMethodDecl *MD = *I; - + for (const auto *MD : RD->methods()) { if (!MD->isVirtual()) continue; @@ -1759,13 +1758,12 @@ ItaniumVTableBuilder::LayoutSecondaryVTables(BaseSubobject Base, const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { + for (const auto &B : RD->bases()) { // Ignore virtual bases, we'll emit them later. - if (I->isVirtual()) + if (B.isVirtual()) continue; - const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl(); + const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); // Ignore bases that don't have a vtable. if (!BaseDecl->isDynamicClass()) @@ -1838,13 +1836,12 @@ void ItaniumVTableBuilder::DeterminePrimaryVirtualBases( } // Traverse bases, looking for more primary virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl(); + for (const auto &B : RD->bases()) { + const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); CharUnits BaseOffsetInLayoutClass; - if (I->isVirtual()) { + if (B.isVirtual()) { if (!VBases.insert(BaseDecl)) continue; @@ -1868,13 +1865,12 @@ void ItaniumVTableBuilder::LayoutVTablesForVirtualBases( // Then come the virtual base virtual tables, also in inheritance graph // order, and again excluding primary bases (which share virtual tables with // the classes for which they are primary). - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl(); + for (const auto &B : RD->bases()) { + const CXXRecordDecl *BaseDecl = B.getType()->getAsCXXRecordDecl(); // Check if this base needs a vtable. (If it's virtual, not a primary base // of some other class, and we haven't visited it before). - if (I->isVirtual() && BaseDecl->isDynamicClass() && + if (B.isVirtual() && BaseDecl->isDynamicClass() && !PrimaryVirtualBases.count(BaseDecl) && VBases.insert(BaseDecl)) { const ASTRecordLayout &MostDerivedClassLayout = Context.getASTRecordLayout(MostDerivedClass); @@ -1900,21 +1896,6 @@ void ItaniumVTableBuilder::LayoutVTablesForVirtualBases( } } -struct ItaniumThunkInfoComparator { - bool operator() (const ThunkInfo &LHS, const ThunkInfo &RHS) { - assert(LHS.Method == 0); - assert(RHS.Method == 0); - - if (LHS.This != RHS.This) - return LHS.This < RHS.This; - - if (LHS.Return != RHS.Return) - return LHS.Return < RHS.Return; - - return false; - } -}; - /// dumpLayout - Dump the vtable layout. void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { // FIXME: write more tests that actually use the dumpLayout output to prevent @@ -1922,12 +1903,13 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { if (isBuildingConstructorVTable()) { Out << "Construction vtable for ('"; - Out << MostDerivedClass->getQualifiedNameAsString() << "', "; + MostDerivedClass->printQualifiedName(Out); + Out << "', "; Out << MostDerivedClassOffset.getQuantity() << ") in '"; - Out << LayoutClass->getQualifiedNameAsString(); + LayoutClass->printQualifiedName(Out); } else { Out << "Vtable for '"; - Out << MostDerivedClass->getQualifiedNameAsString(); + MostDerivedClass->printQualifiedName(Out); } Out << "' (" << Components.size() << " entries).\n"; @@ -1973,7 +1955,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { break; case VTableComponent::CK_RTTI: - Out << Component.getRTTIDecl()->getQualifiedNameAsString() << " RTTI"; + Component.getRTTIDecl()->printQualifiedName(Out); + Out << " RTTI"; break; case VTableComponent::CK_FunctionPointer: { @@ -2028,7 +2011,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { const CXXDestructorDecl *DD = Component.getDestructorDecl(); - Out << DD->getQualifiedNameAsString(); + DD->printQualifiedName(Out); if (IsComplete) Out << "() [complete]"; else @@ -2078,7 +2061,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { const BaseSubobject &Base = AddressPointsByIndex.find(NextIndex)->second; - Out << " -- (" << Base.getBase()->getQualifiedNameAsString(); + Out << " -- ("; + Base.getBase()->printQualifiedName(Out); Out << ", " << Base.getBaseOffset().getQuantity(); Out << ") vtable address --\n"; } else { @@ -2124,7 +2108,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { } Out << "Virtual base offset offsets for '"; - Out << MostDerivedClass->getQualifiedNameAsString() << "' ("; + MostDerivedClass->printQualifiedName(Out); + Out << "' ("; Out << ClassNamesAndOffsets.size(); Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n"; @@ -2158,7 +2143,10 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { ThunkInfoVectorTy ThunksVector = Thunks[MD]; std::sort(ThunksVector.begin(), ThunksVector.end(), - ItaniumThunkInfoComparator()); + [](const ThunkInfo &LHS, const ThunkInfo &RHS) { + assert(LHS.Method == nullptr && RHS.Method == nullptr); + return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return); + }); Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size(); Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n"; @@ -2203,10 +2191,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { // Store them in a map keyed by the index so we'll get a sorted table. std::map<uint64_t, std::string> IndicesMap; - for (CXXRecordDecl::method_iterator i = MostDerivedClass->method_begin(), - e = MostDerivedClass->method_end(); i != e; ++i) { - const CXXMethodDecl *MD = *i; - + for (const auto *MD : MostDerivedClass->methods()) { // We only want virtual member functions. if (!MD->isVirtual()) continue; @@ -2230,7 +2215,7 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { // Print the vtable indices for all the member functions. if (!IndicesMap.empty()) { Out << "VTable indices for '"; - Out << MostDerivedClass->getQualifiedNameAsString(); + MostDerivedClass->printQualifiedName(Out); Out << "' (" << IndicesMap.size() << " entries).\n"; for (std::map<uint64_t, std::string>::const_iterator I = IndicesMap.begin(), @@ -2245,17 +2230,6 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { Out << '\n'; } - -struct VTableThunksComparator { - bool operator()(const VTableLayout::VTableThunkTy &LHS, - const VTableLayout::VTableThunkTy &RHS) { - if (LHS.first == RHS.first) { - assert(LHS.second == RHS.second && - "Different thunks should have unique indices!"); - } - return LHS.first < RHS.first; - } -}; } VTableLayout::VTableLayout(uint64_t NumVTableComponents, @@ -2276,14 +2250,18 @@ VTableLayout::VTableLayout(uint64_t NumVTableComponents, this->VTableThunks.get()); std::sort(this->VTableThunks.get(), this->VTableThunks.get() + NumVTableThunks, - VTableThunksComparator()); + [](const VTableLayout::VTableThunkTy &LHS, + const VTableLayout::VTableThunkTy &RHS) { + assert((LHS.first != RHS.first || LHS.second == RHS.second) && + "Different thunks should have unique indices!"); + return LHS.first < RHS.first; + }); } VTableLayout::~VTableLayout() { } ItaniumVTableContext::ItaniumVTableContext(ASTContext &Context) - : IsMicrosoftABI(Context.getTargetInfo().getCXXABI().isMicrosoft()) { -} + : VTableContextBase(/*MS=*/false) {} ItaniumVTableContext::~ItaniumVTableContext() { llvm::DeleteContainerSeconds(VTableLayouts); @@ -2312,8 +2290,8 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, VirtualBaseClassOffsetOffsets.find(ClassPair); if (I != VirtualBaseClassOffsetOffsets.end()) return I->second; - - VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/0, + + VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/nullptr, BaseSubobject(RD, CharUnits::Zero()), /*BaseIsVirtual=*/false, /*OffsetInLayoutClass=*/CharUnits::Zero()); @@ -2348,8 +2326,6 @@ static VTableLayout *CreateVTableLayout(const ItaniumVTableBuilder &Builder) { void ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) { - assert(!IsMicrosoftABI && "Shouldn't be called in this ABI!"); - const VTableLayout *&Entry = VTableLayouts[RD]; // Check if we've computed this information before. @@ -2444,6 +2420,9 @@ public: typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation> MethodVFTableLocationsTy; + typedef llvm::iterator_range<MethodVFTableLocationsTy::const_iterator> + method_locations_range; + private: /// VTables - Global vtable information. MicrosoftVTableContext &VTables; @@ -2457,7 +2436,7 @@ private: const ASTRecordLayout &MostDerivedClassLayout; - VFPtrInfo WhichVFPtr; + const VPtrInfo &WhichVFPtr; /// FinalOverriders - The final overriders of the most derived class. const FinalOverriders Overriders; @@ -2467,6 +2446,9 @@ private: MethodVFTableLocationsTy MethodVFTableLocations; + /// \brief Does this class have an RTTI component? + bool HasRTTIComponent; + /// MethodInfo - Contains information about a method in a vtable. /// (Used for computing 'this' pointer adjustment thunks. struct MethodInfo { @@ -2521,11 +2503,8 @@ private: } /// ComputeThisOffset - Returns the 'this' argument offset for the given - /// method in the given subobject, relative to the beginning of the - /// MostDerivedClass. - CharUnits ComputeThisOffset(const CXXMethodDecl *MD, - BaseSubobject Base, - FinalOverriders::OverriderInfo Overrider); + /// method, relative to the beginning of the MostDerivedClass. + CharUnits ComputeThisOffset(FinalOverriders::OverriderInfo Overrider); void CalculateVtordispAdjustment(FinalOverriders::OverriderInfo Overrider, CharUnits ThisOffset, ThisAdjustment &TA); @@ -2533,17 +2512,21 @@ private: /// AddMethod - Add a single virtual member function to the vftable /// components vector. void AddMethod(const CXXMethodDecl *MD, ThunkInfo TI) { + if (!TI.isEmpty()) { + VTableThunks[Components.size()] = TI; + AddThunk(MD, TI); + } if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { assert(TI.Return.isEmpty() && "Destructor can't have return adjustment!"); Components.push_back(VTableComponent::MakeDeletingDtor(DD)); } else { - if (!TI.isEmpty()) - VTableThunks[Components.size()] = TI; Components.push_back(VTableComponent::MakeFunction(MD)); } } + bool NeedsReturnAdjustingThunk(const CXXMethodDecl *MD); + /// AddMethods - Add the methods of this base subobject and the relevant /// subbases to the vftable we're currently laying out. void AddMethods(BaseSubobject Base, unsigned BaseDepth, @@ -2555,8 +2538,9 @@ private: // pointing to the middle of a section. BasesSetVectorTy VisitedBases; - AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, 0, + AddMethods(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 0, nullptr, VisitedBases); + assert(Components.size() && "vftable can't be empty"); assert(MethodVFTableLocations.empty()); for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(), @@ -2567,8 +2551,8 @@ private: // and the entries shadowed by return adjusting thunks. if (MD->getParent() != MostDerivedClass || MI.Shadowed) continue; - MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.LastVBase, - WhichVFPtr.VFPtrOffset, MI.VFTableIndex); + MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(), + WhichVFPtr.NonVirtualOffset, MI.VFTableIndex); if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc; } else { @@ -2586,13 +2570,20 @@ private: public: VFTableBuilder(MicrosoftVTableContext &VTables, - const CXXRecordDecl *MostDerivedClass, VFPtrInfo Which) + const CXXRecordDecl *MostDerivedClass, const VPtrInfo *Which) : VTables(VTables), Context(MostDerivedClass->getASTContext()), MostDerivedClass(MostDerivedClass), MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)), - WhichVFPtr(Which), + WhichVFPtr(*Which), Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) { + // Only include the RTTI component if we know that we will provide a + // definition of the vftable. + HasRTTIComponent = Context.getLangOpts().RTTIData && + !MostDerivedClass->hasAttr<DLLImportAttr>(); + if (HasRTTIComponent) + Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass)); + LayoutVFTable(); if (Context.getLangOpts().DumpVTableLayouts) @@ -2605,12 +2596,9 @@ public: ThunksMapTy::const_iterator thunks_end() const { return Thunks.end(); } - MethodVFTableLocationsTy::const_iterator vtable_indices_begin() const { - return MethodVFTableLocations.begin(); - } - - MethodVFTableLocationsTy::const_iterator vtable_indices_end() const { - return MethodVFTableLocations.end(); + method_locations_range vtable_locations() const { + return method_locations_range(MethodVFTableLocations.begin(), + MethodVFTableLocations.end()); } uint64_t getNumVTableComponents() const { return Components.size(); } @@ -2634,6 +2622,8 @@ public: void dumpLayout(raw_ostream &); }; +} // end namespace + /// InitialOverriddenDefinitionCollector - Finds the set of least derived bases /// that define the given method. struct InitialOverriddenDefinitionCollector { @@ -2655,14 +2645,18 @@ static bool BaseInSet(const CXXBaseSpecifier *Specifier, } CharUnits -VFTableBuilder::ComputeThisOffset(const CXXMethodDecl *MD, - BaseSubobject Base, - FinalOverriders::OverriderInfo Overrider) { +VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) { InitialOverriddenDefinitionCollector Collector; - visitAllOverriddenMethods(MD, Collector); + visitAllOverriddenMethods(Overrider.Method, Collector); + + // If there are no overrides then 'this' is located + // in the base that defines the method. + if (Collector.Bases.size() == 0) + return Overrider.Offset; CXXBasePaths Paths; - Base.getBase()->lookupInBases(BaseInSet, &Collector.Bases, Paths); + Overrider.Method->getParent()->lookupInBases(BaseInSet, &Collector.Bases, + Paths); // This will hold the smallest this offset among overridees of MD. // This implies that an offset of a non-virtual base will dominate an offset @@ -2671,10 +2665,12 @@ VFTableBuilder::ComputeThisOffset(const CXXMethodDecl *MD, CharUnits Ret; bool First = true; + const ASTRecordLayout &OverriderRDLayout = + Context.getASTRecordLayout(Overrider.Method->getParent()); for (CXXBasePaths::paths_iterator I = Paths.begin(), E = Paths.end(); I != E; ++I) { const CXXBasePath &Path = (*I); - CharUnits ThisOffset = Base.getBaseOffset(); + CharUnits ThisOffset = Overrider.Offset; CharUnits LastVBaseOffset; // For each path from the overrider to the parents of the overridden methods, @@ -2687,34 +2683,33 @@ VFTableBuilder::ComputeThisOffset(const CXXMethodDecl *MD, const ASTRecordLayout &Layout = Context.getASTRecordLayout(PrevRD); if (Element.Base->isVirtual()) { - LastVBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(CurRD); - if (Overrider.Method->getParent() == PrevRD) { - // This one's interesting. If the final overrider is in a vbase B of the - // most derived class and it overrides a method of the B's own vbase A, - // it uses A* as "this". In its prologue, it can cast A* to B* with - // a static offset. This offset is used regardless of the actual - // offset of A from B in the most derived class, requiring an - // this-adjusting thunk in the vftable if A and B are laid out - // differently in the most derived class. - ThisOffset += Layout.getVBaseClassOffset(CurRD); - } else { - ThisOffset = LastVBaseOffset; - } + // The interesting things begin when you have virtual inheritance. + // The final overrider will use a static adjustment equal to the offset + // of the vbase in the final overrider class. + // For example, if the final overrider is in a vbase B of the most + // derived class and it overrides a method of the B's own vbase A, + // it uses A* as "this". In its prologue, it can cast A* to B* with + // a static offset. This offset is used regardless of the actual + // offset of A from B in the most derived class, requiring an + // this-adjusting thunk in the vftable if A and B are laid out + // differently in the most derived class. + LastVBaseOffset = ThisOffset = + Overrider.Offset + OverriderRDLayout.getVBaseClassOffset(CurRD); } else { ThisOffset += Layout.getBaseClassOffset(CurRD); } } - if (isa<CXXDestructorDecl>(MD)) { + if (isa<CXXDestructorDecl>(Overrider.Method)) { if (LastVBaseOffset.isZero()) { // If a "Base" class has at least one non-virtual base with a virtual // destructor, the "Base" virtual destructor will take the address // of the "Base" subobject as the "this" argument. - return Base.getBaseOffset(); + ThisOffset = Overrider.Offset; } else { // A virtual destructor of a virtual base takes the address of the // virtual base subobject as the "this" argument. - return LastVBaseOffset; + ThisOffset = LastVBaseOffset; } } @@ -2734,39 +2729,35 @@ void VFTableBuilder::CalculateVtordispAdjustment( const ASTRecordLayout::VBaseOffsetsMapTy &VBaseMap = MostDerivedClassLayout.getVBaseOffsetsMap(); const ASTRecordLayout::VBaseOffsetsMapTy::const_iterator &VBaseMapEntry = - VBaseMap.find(WhichVFPtr.LastVBase); + VBaseMap.find(WhichVFPtr.getVBaseWithVPtr()); assert(VBaseMapEntry != VBaseMap.end()); - // Check if we need a vtordisp adjustment at all. - if (!VBaseMapEntry->second.hasVtorDisp()) + // If there's no vtordisp or the final overrider is defined in the same vbase + // as the initial declaration, we don't need any vtordisp adjustment. + if (!VBaseMapEntry->second.hasVtorDisp() || + Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr()) return; - CharUnits VFPtrVBaseOffset = VBaseMapEntry->second.VBaseOffset; + // OK, now we know we need to use a vtordisp thunk. // The implicit vtordisp field is located right before the vbase. + CharUnits VFPtrVBaseOffset = VBaseMapEntry->second.VBaseOffset; TA.Virtual.Microsoft.VtordispOffset = - (VFPtrVBaseOffset - WhichVFPtr.VFPtrFullOffset).getQuantity() - 4; - - // If the final overrider is defined in either: - // - the most derived class or its non-virtual base or - // - the same vbase as the initial declaration, - // a simple vtordisp thunk will suffice. - const CXXRecordDecl *OverriderRD = Overrider.Method->getParent(); - if (OverriderRD == MostDerivedClass) - return; + (VFPtrVBaseOffset - WhichVFPtr.FullOffsetInMDC).getQuantity() - 4; - const CXXRecordDecl *OverriderVBase = - ComputeBaseOffset(Context, OverriderRD, MostDerivedClass).VirtualBase; - if (!OverriderVBase || OverriderVBase == WhichVFPtr.LastVBase) + // A simple vtordisp thunk will suffice if the final overrider is defined + // in either the most derived class or its non-virtual base. + if (Overrider.Method->getParent() == MostDerivedClass || + !Overrider.VirtualBase) return; // Otherwise, we need to do use the dynamic offset of the final overrider // in order to get "this" adjustment right. TA.Virtual.Microsoft.VBPtrOffset = - (VFPtrVBaseOffset + WhichVFPtr.VFPtrOffset - + (VFPtrVBaseOffset + WhichVFPtr.NonVirtualOffset - MostDerivedClassLayout.getVBPtrOffset()).getQuantity(); TA.Virtual.Microsoft.VBOffsetOffset = Context.getTypeSizeInChars(Context.IntTy).getQuantity() * - VTables.getVBTableIndex(MostDerivedClass, OverriderVBase); + VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase); TA.NonVirtual = (ThisOffset - Overrider.Offset).getQuantity(); } @@ -2777,25 +2768,20 @@ static void GroupNewVirtualOverloads( // Put the virtual methods into VirtualMethods in the proper order: // 1) Group overloads by declaration name. New groups are added to the // vftable in the order of their first declarations in this class - // (including overrides). + // (including overrides and non-virtual methods). // 2) In each group, new overloads appear in the reverse order of declaration. typedef SmallVector<const CXXMethodDecl *, 1> MethodGroup; SmallVector<MethodGroup, 10> Groups; typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy; VisitedGroupIndicesTy VisitedGroupIndices; - for (CXXRecordDecl::method_iterator I = RD->method_begin(), - E = RD->method_end(); I != E; ++I) { - const CXXMethodDecl *MD = *I; - if (!MD->isVirtual()) - continue; - + for (const auto *MD : RD->methods()) { VisitedGroupIndicesTy::iterator J; bool Inserted; - llvm::tie(J, Inserted) = VisitedGroupIndices.insert( + std::tie(J, Inserted) = VisitedGroupIndices.insert( std::make_pair(MD->getDeclName(), Groups.size())); if (Inserted) - Groups.push_back(MethodGroup(1, MD)); - else + Groups.push_back(MethodGroup()); + if (MD->isVirtual()) Groups[J->second].push_back(MD); } @@ -2803,6 +2789,32 @@ static void GroupNewVirtualOverloads( VirtualMethods.append(Groups[I].rbegin(), Groups[I].rend()); } +/// We need a return adjusting thunk for this method if its return type is +/// not trivially convertible to the return type of any of its overridden +/// methods. +bool VFTableBuilder::NeedsReturnAdjustingThunk(const CXXMethodDecl *MD) { + OverriddenMethodsSetTy OverriddenMethods; + ComputeAllOverriddenMethods(MD, OverriddenMethods); + for (OverriddenMethodsSetTy::iterator I = OverriddenMethods.begin(), + E = OverriddenMethods.end(); + I != E; ++I) { + const CXXMethodDecl *OverriddenMD = *I; + BaseOffset Adjustment = + ComputeReturnAdjustmentBaseOffset(Context, MD, OverriddenMD); + if (!Adjustment.isEmpty()) + return true; + } + return false; +} + +static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD) { + for (const auto &B : RD->bases()) { + if (B.isVirtual() && B.getType()->getAsCXXRecordDecl() == Base) + return true; + } + return false; +} + void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, const CXXRecordDecl *LastVBase, BasesSetVectorTy &VisitedBases) { @@ -2814,11 +2826,11 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // See if this class expands a vftable of the base we look at, which is either // the one defined by the vfptr base path or the primary base of the current class. - const CXXRecordDecl *NextBase = 0, *NextLastVBase = LastVBase; + const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase; CharUnits NextBaseOffset; - if (BaseDepth < WhichVFPtr.PathToBaseWithVFPtr.size()) { - NextBase = WhichVFPtr.PathToBaseWithVFPtr[BaseDepth]; - if (Layout.getVBaseOffsetsMap().count(NextBase)) { + if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) { + NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth]; + if (isDirectVBase(NextBase, RD)) { NextLastVBase = NextBase; NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase); } else { @@ -2856,13 +2868,21 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, FinalOverriders::OverriderInfo Overrider = Overriders.getOverrider(MD, Base.getBaseOffset()); - ThisAdjustment ThisAdjustmentOffset; - bool ForceThunk = false; + const CXXMethodDecl *OverriderMD = Overrider.Method; + const CXXMethodDecl *OverriddenMD = + FindNearestOverriddenMethod(MD, VisitedBases); - // Check if this virtual member function overrides - // a method in one of the visited bases. - if (const CXXMethodDecl *OverriddenMD = - FindNearestOverriddenMethod(MD, VisitedBases)) { + ThisAdjustment ThisAdjustmentOffset; + bool ReturnAdjustingThunk = false; + CharUnits ThisOffset = ComputeThisOffset(Overrider); + ThisAdjustmentOffset.NonVirtual = + (ThisOffset - WhichVFPtr.FullOffsetInMDC).getQuantity(); + if ((OverriddenMD || OverriderMD != MD) && + WhichVFPtr.getVBaseWithVPtr()) + CalculateVtordispAdjustment(Overrider, ThisOffset, ThisAdjustmentOffset); + + if (OverriddenMD) { + // If MD overrides anything in this vftable, we need to update the entries. MethodInfoMapTy::iterator OverriddenMDIterator = MethodInfoMap.find(OverriddenMD); @@ -2872,23 +2892,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second; - // Create a this-adjusting thunk if needed. - CharUnits TI = ComputeThisOffset(MD, Base, Overrider); - if (TI != WhichVFPtr.VFPtrFullOffset) { - ThisAdjustmentOffset.NonVirtual = - (TI - WhichVFPtr.VFPtrFullOffset).getQuantity(); - } - - if (WhichVFPtr.LastVBase) - CalculateVtordispAdjustment(Overrider, TI, ThisAdjustmentOffset); - - if (!ThisAdjustmentOffset.isEmpty()) { - VTableThunks[OverriddenMethodInfo.VFTableIndex].This = - ThisAdjustmentOffset; - AddThunk(MD, VTableThunks[OverriddenMethodInfo.VFTableIndex]); - } - - if (MD->getResultType() == OverriddenMD->getResultType()) { + if (!NeedsReturnAdjustingThunk(MD)) { // No return adjustment needed - just replace the overridden method info // with the current info. MethodInfo MI(OverriddenMethodInfo.VBTableIndex, @@ -2899,33 +2903,17 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, "Should not have method info for this method yet!"); MethodInfoMap.insert(std::make_pair(MD, MI)); continue; - } else { - // In case we need a return adjustment, we'll add a new slot for - // the overrider and put a return-adjusting thunk where the overridden - // method was in the vftable. - // For now, just mark the overriden method as shadowed by a new slot. - OverriddenMethodInfo.Shadowed = true; - ForceThunk = true; - - // Also apply this adjustment to the shadowed slots. - if (!ThisAdjustmentOffset.isEmpty()) { - // FIXME: this is O(N^2), can be O(N). - const CXXMethodDecl *SubOverride = OverriddenMD; - while ((SubOverride = - FindNearestOverriddenMethod(SubOverride, VisitedBases))) { - MethodInfoMapTy::iterator SubOverrideIterator = - MethodInfoMap.find(SubOverride); - if (SubOverrideIterator == MethodInfoMap.end()) - break; - MethodInfo &SubOverrideMI = SubOverrideIterator->second; - assert(SubOverrideMI.Shadowed); - VTableThunks[SubOverrideMI.VFTableIndex].This = - ThisAdjustmentOffset; - AddThunk(MD, VTableThunks[SubOverrideMI.VFTableIndex]); - } - } } - } else if (Base.getBaseOffset() != WhichVFPtr.VFPtrFullOffset || + + // In case we need a return adjustment, we'll add a new slot for + // the overrider. Mark the overriden method as shadowed by the new slot. + OverriddenMethodInfo.Shadowed = true; + + // Force a special name mangling for a return-adjusting thunk + // unless the method is the final overrider without this adjustment. + ReturnAdjustingThunk = + !(MD == OverriderMD && ThisAdjustmentOffset.isEmpty()); + } else if (Base.getBaseOffset() != WhichVFPtr.FullOffsetInMDC || MD->size_overridden_methods()) { // Skip methods that don't belong to the vftable of the current class, // e.g. each method that wasn't seen in any of the visited sub-bases @@ -2937,14 +2925,13 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // it requires return adjustment. Insert the method info for this method. unsigned VBIndex = LastVBase ? VTables.getVBTableIndex(MostDerivedClass, LastVBase) : 0; - MethodInfo MI(VBIndex, Components.size()); + MethodInfo MI(VBIndex, + HasRTTIComponent ? Components.size() - 1 : Components.size()); assert(!MethodInfoMap.count(MD) && "Should not have method info for this method yet!"); MethodInfoMap.insert(std::make_pair(MD, MI)); - const CXXMethodDecl *OverriderMD = Overrider.Method; - // Check if this overrider needs a return adjustment. // We don't want to do this for pure virtual member functions. BaseOffset ReturnAdjustmentOffset; @@ -2954,7 +2941,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD); } if (!ReturnAdjustmentOffset.isEmpty()) { - ForceThunk = true; + ReturnAdjustingThunk = true; ReturnAdjustment.NonVirtual = ReturnAdjustmentOffset.NonVirtualOffset.getQuantity(); if (ReturnAdjustmentOffset.VirtualBase) { @@ -2969,40 +2956,30 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, } AddMethod(OverriderMD, ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment, - ForceThunk ? MD : 0)); + ReturnAdjustingThunk ? MD : nullptr)); } } -void PrintBasePath(const VFPtrInfo::BasePath &Path, raw_ostream &Out) { - for (VFPtrInfo::BasePath::const_reverse_iterator I = Path.rbegin(), +static void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out) { + for (VPtrInfo::BasePath::const_reverse_iterator I = Path.rbegin(), E = Path.rend(); I != E; ++I) { - Out << "'" << (*I)->getQualifiedNameAsString() << "' in "; + Out << "'"; + (*I)->printQualifiedName(Out); + Out << "' in "; } } -struct MicrosoftThunkInfoStableSortComparator { - bool operator() (const ThunkInfo &LHS, const ThunkInfo &RHS) { - if (LHS.This != RHS.This) - return LHS.This < RHS.This; - - if (LHS.Return != RHS.Return) - return LHS.Return < RHS.Return; - - // Keep different thunks with the same adjustments in the order they - // were put into the vector. - return false; - } -}; - static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, bool ContinueFirstLine) { const ReturnAdjustment &R = TI.Return; bool Multiline = false; - const char *LinePrefix = "\n "; - if (!R.isEmpty()) { + const char *LinePrefix = "\n "; + if (!R.isEmpty() || TI.Method) { if (!ContinueFirstLine) Out << LinePrefix; - Out << "[return adjustment: "; + Out << "[return adjustment (to type '" + << TI.Method->getReturnType().getCanonicalType().getAsString() + << "'): "; if (R.Virtual.Microsoft.VBPtrOffset) Out << "vbptr at offset " << R.Virtual.Microsoft.VBPtrOffset << ", "; if (R.Virtual.Microsoft.VBIndex) @@ -3021,7 +2998,7 @@ static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, Out << "vtordisp at " << T.Virtual.Microsoft.VtordispOffset << ", "; if (T.Virtual.Microsoft.VBPtrOffset) { Out << "vbptr at " << T.Virtual.Microsoft.VBPtrOffset - << " to the left, "; + << " to the left,"; assert(T.Virtual.Microsoft.VBOffsetOffset > 0); Out << LinePrefix << " vboffset at " << T.Virtual.Microsoft.VBOffsetOffset << " in the vbtable, "; @@ -3033,9 +3010,11 @@ static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out, void VFTableBuilder::dumpLayout(raw_ostream &Out) { Out << "VFTable for "; - PrintBasePath(WhichVFPtr.PathToBaseWithVFPtr, Out); - Out << "'" << MostDerivedClass->getQualifiedNameAsString(); - Out << "' (" << Components.size() << " entries).\n"; + PrintBasePath(WhichVFPtr.PathToBaseWithVPtr, Out); + Out << "'"; + MostDerivedClass->printQualifiedName(Out); + Out << "' (" << Components.size() + << (Components.size() == 1 ? " entry" : " entries") << ").\n"; for (unsigned I = 0, E = Components.size(); I != E; ++I) { Out << llvm::format("%4d | ", I); @@ -3045,12 +3024,15 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { // Dump the component. switch (Component.getKind()) { case VTableComponent::CK_RTTI: - Out << Component.getRTTIDecl()->getQualifiedNameAsString() << " RTTI"; + Component.getRTTIDecl()->printQualifiedName(Out); + Out << " RTTI"; break; case VTableComponent::CK_FunctionPointer: { const CXXMethodDecl *MD = Component.getFunctionDecl(); + // FIXME: Figure out how to print the real thunk type, since they can + // differ in the return type. std::string Str = PredefinedExpr::ComputeName( PredefinedExpr::PrettyFunctionNoVirtual, MD); Out << Str; @@ -3072,7 +3054,7 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { case VTableComponent::CK_DeletingDtorPointer: { const CXXDestructorDecl *DD = Component.getDestructorDecl(); - Out << DD->getQualifiedNameAsString(); + DD->printQualifiedName(Out); Out << "() [scalar deleting]"; if (DD->isPure()) @@ -3124,7 +3106,11 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { ThunkInfoVectorTy ThunksVector = Thunks[MD]; std::stable_sort(ThunksVector.begin(), ThunksVector.end(), - MicrosoftThunkInfoStableSortComparator()); + [](const ThunkInfo &LHS, const ThunkInfo &RHS) { + // Keep different thunks with the same adjustments in the order they + // were put into the vector. + return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return); + }); Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size(); Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n"; @@ -3140,123 +3126,170 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { Out << '\n'; } } -} + + Out.flush(); } -void MicrosoftVTableContext::enumerateVFPtrs( - const CXXRecordDecl *MostDerivedClass, - const ASTRecordLayout &MostDerivedClassLayout, BaseSubobject Base, - const CXXRecordDecl *LastVBase, - const VFPtrInfo::BasePath &PathFromCompleteClass, - BasesSetVectorTy &VisitedVBases, - VFPtrListTy &Result) { - const CXXRecordDecl *CurrentClass = Base.getBase(); - CharUnits OffsetInCompleteClass = Base.getBaseOffset(); - const ASTRecordLayout &CurrentClassLayout = - Context.getASTRecordLayout(CurrentClass); - - if (CurrentClassLayout.hasOwnVFPtr()) { - if (LastVBase) { - uint64_t VBIndex = getVBTableIndex(MostDerivedClass, LastVBase); - assert(VBIndex > 0 && "vbases must have vbindex!"); - CharUnits VFPtrOffset = - OffsetInCompleteClass - - MostDerivedClassLayout.getVBaseClassOffset(LastVBase); - Result.push_back(VFPtrInfo(VBIndex, LastVBase, VFPtrOffset, - PathFromCompleteClass, OffsetInCompleteClass)); - } else { - Result.push_back(VFPtrInfo(OffsetInCompleteClass, PathFromCompleteClass)); - } +static bool setsIntersect(const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &A, + const ArrayRef<const CXXRecordDecl *> &B) { + for (ArrayRef<const CXXRecordDecl *>::iterator I = B.begin(), E = B.end(); + I != E; ++I) { + if (A.count(*I)) + return true; } + return false; +} - for (CXXRecordDecl::base_class_const_iterator I = CurrentClass->bases_begin(), - E = CurrentClass->bases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl(); +static bool rebucketPaths(VPtrInfoVector &Paths); - CharUnits NextBaseOffset; - const CXXRecordDecl *NextLastVBase; - if (I->isVirtual()) { - if (!VisitedVBases.insert(BaseDecl)) - continue; - NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); - NextLastVBase = BaseDecl; - } else { - NextBaseOffset = OffsetInCompleteClass + - CurrentClassLayout.getBaseClassOffset(BaseDecl); - NextLastVBase = LastVBase; - } +/// Produces MSVC-compatible vbtable data. The symbols produced by this +/// algorithm match those produced by MSVC 2012 and newer, which is different +/// from MSVC 2010. +/// +/// MSVC 2012 appears to minimize the vbtable names using the following +/// algorithm. First, walk the class hierarchy in the usual order, depth first, +/// left to right, to find all of the subobjects which contain a vbptr field. +/// Visiting each class node yields a list of inheritance paths to vbptrs. Each +/// record with a vbptr creates an initially empty path. +/// +/// To combine paths from child nodes, the paths are compared to check for +/// ambiguity. Paths are "ambiguous" if multiple paths have the same set of +/// components in the same order. Each group of ambiguous paths is extended by +/// appending the class of the base from which it came. If the current class +/// node produced an ambiguous path, its path is extended with the current class. +/// After extending paths, MSVC again checks for ambiguity, and extends any +/// ambiguous path which wasn't already extended. Because each node yields an +/// unambiguous set of paths, MSVC doesn't need to extend any path more than once +/// to produce an unambiguous set of paths. +/// +/// TODO: Presumably vftables use the same algorithm. +void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, + const CXXRecordDecl *RD, + VPtrInfoVector &Paths) { + assert(Paths.empty()); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - VFPtrInfo::BasePath NewPath = PathFromCompleteClass; - NewPath.push_back(BaseDecl); - BaseSubobject NextBase(BaseDecl, NextBaseOffset); + // Base case: this subobject has its own vptr. + if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr()) + Paths.push_back(new VPtrInfo(RD)); - enumerateVFPtrs(MostDerivedClass, MostDerivedClassLayout, NextBase, - NextLastVBase, NewPath, VisitedVBases, Result); - } -} + // Recursive case: get all the vbtables from our bases and remove anything + // that shares a virtual base. + llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen; + for (const auto &B : RD->bases()) { + const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl(); + if (B.isVirtual() && VBasesSeen.count(Base)) + continue; -/// CalculatePathToMangle - Calculate the subset of records that should be used -/// to mangle the vftable for the given vfptr. -/// Should only be called if a class has multiple vftables. -static void -CalculatePathToMangle(const CXXRecordDecl *RD, VFPtrInfo &VFPtr) { - // FIXME: In some rare cases this code produces a slightly incorrect mangling. - // It's very likely that the vbtable mangling code can be adjusted to mangle - // both vftables and vbtables correctly. - - VFPtrInfo::BasePath &FullPath = VFPtr.PathToBaseWithVFPtr; - if (FullPath.empty()) { - // Mangle the class's own vftable. - assert(RD->getNumVBases() && - "Something's wrong: if the most derived " - "class has more than one vftable, it can only have its own " - "vftable if it has vbases"); - VFPtr.PathToMangle.push_back(RD); - return; - } + if (!Base->isDynamicClass()) + continue; + + const VPtrInfoVector &BasePaths = + ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base); - unsigned Begin = 0; + for (VPtrInfo *BaseInfo : BasePaths) { + // Don't include the path if it goes through a virtual base that we've + // already included. + if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases)) + continue; - // First, skip all the bases before the vbase. - if (VFPtr.LastVBase) { - while (FullPath[Begin] != VFPtr.LastVBase) { - Begin++; - assert(Begin < FullPath.size()); + // Copy the path and adjust it as necessary. + VPtrInfo *P = new VPtrInfo(*BaseInfo); + + // We mangle Base into the path if the path would've been ambiguous and it + // wasn't already extended with Base. + if (P->MangledPath.empty() || P->MangledPath.back() != Base) + P->NextBaseToMangle = Base; + + // Keep track of the full path. + // FIXME: Why do we need this? + P->PathToBaseWithVPtr.insert(P->PathToBaseWithVPtr.begin(), Base); + + // Keep track of which vtable the derived class is going to extend with + // new methods or bases. We append to either the vftable of our primary + // base, or the first non-virtual base that has a vbtable. + if (P->ReusingBase == Base && + Base == (ForVBTables ? Layout.getBaseSharingVBPtr() + : Layout.getPrimaryBase())) + P->ReusingBase = RD; + + // Keep track of the full adjustment from the MDC to this vtable. The + // adjustment is captured by an optional vbase and a non-virtual offset. + if (B.isVirtual()) + P->ContainingVBases.push_back(Base); + else if (P->ContainingVBases.empty()) + P->NonVirtualOffset += Layout.getBaseClassOffset(Base); + + // Update the full offset in the MDC. + P->FullOffsetInMDC = P->NonVirtualOffset; + if (const CXXRecordDecl *VB = P->getVBaseWithVPtr()) + P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB); + + Paths.push_back(P); } + + if (B.isVirtual()) + VBasesSeen.insert(Base); + + // After visiting any direct base, we've transitively visited all of its + // morally virtual bases. + for (const auto &VB : Base->vbases()) + VBasesSeen.insert(VB.getType()->getAsCXXRecordDecl()); } - // Then, put the rest of the base path in the reverse order. - for (unsigned I = FullPath.size(); I != Begin; --I) { - const CXXRecordDecl *CurBase = FullPath[I - 1], - *ItsBase = (I == 1) ? RD : FullPath[I - 2]; - bool BaseIsVirtual = false; - for (CXXRecordDecl::base_class_const_iterator J = ItsBase->bases_begin(), - F = ItsBase->bases_end(); J != F; ++J) { - if (J->getType()->getAsCXXRecordDecl() == CurBase) { - BaseIsVirtual = J->isVirtual(); - break; - } - } + // Sort the paths into buckets, and if any of them are ambiguous, extend all + // paths in ambiguous buckets. + bool Changed = true; + while (Changed) + Changed = rebucketPaths(Paths); +} - // Should skip the current base if it is a non-virtual base with no siblings. - if (BaseIsVirtual || ItsBase->getNumBases() != 1) - VFPtr.PathToMangle.push_back(CurBase); +static bool extendPath(VPtrInfo *P) { + if (P->NextBaseToMangle) { + P->MangledPath.push_back(P->NextBaseToMangle); + P->NextBaseToMangle = nullptr;// Prevent the path from being extended twice. + return true; } + return false; } -void MicrosoftVTableContext::enumerateVFPtrs( - const CXXRecordDecl *ForClass, - MicrosoftVTableContext::VFPtrListTy &Result) { - Result.clear(); - const ASTRecordLayout &ClassLayout = Context.getASTRecordLayout(ForClass); - BasesSetVectorTy VisitedVBases; - enumerateVFPtrs(ForClass, ClassLayout, - BaseSubobject(ForClass, CharUnits::Zero()), 0, - VFPtrInfo::BasePath(), VisitedVBases, Result); - if (Result.size() > 1) { - for (unsigned I = 0, E = Result.size(); I != E; ++I) - CalculatePathToMangle(ForClass, Result[I]); +static bool rebucketPaths(VPtrInfoVector &Paths) { + // What we're essentially doing here is bucketing together ambiguous paths. + // Any bucket with more than one path in it gets extended by NextBase, which + // is usually the direct base of the inherited the vbptr. This code uses a + // sorted vector to implement a multiset to form the buckets. Note that the + // ordering is based on pointers, but it doesn't change our output order. The + // current algorithm is designed to match MSVC 2012's names. + VPtrInfoVector PathsSorted(Paths); + std::sort(PathsSorted.begin(), PathsSorted.end(), + [](const VPtrInfo *LHS, const VPtrInfo *RHS) { + return LHS->MangledPath < RHS->MangledPath; + }); + bool Changed = false; + for (size_t I = 0, E = PathsSorted.size(); I != E;) { + // Scan forward to find the end of the bucket. + size_t BucketStart = I; + do { + ++I; + } while (I != E && PathsSorted[BucketStart]->MangledPath == + PathsSorted[I]->MangledPath); + + // If this bucket has multiple paths, extend them all. + if (I - BucketStart > 1) { + for (size_t II = BucketStart; II != I; ++II) + Changed |= extendPath(PathsSorted[II]); + assert(Changed && "no paths were extended to fix ambiguity"); + } } + return Changed; +} + +MicrosoftVTableContext::~MicrosoftVTableContext() { + for (auto &P : VFPtrLocations) + llvm::DeleteContainerPointers(*P.second); + llvm::DeleteContainerSeconds(VFPtrLocations); + llvm::DeleteContainerSeconds(VFTableLayouts); + llvm::DeleteContainerSeconds(VBaseInfo); } void MicrosoftVTableContext::computeVTableRelatedInformation( @@ -3269,24 +3302,31 @@ void MicrosoftVTableContext::computeVTableRelatedInformation( const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap; - VFPtrListTy &VFPtrs = VFPtrLocations[RD]; - enumerateVFPtrs(RD, VFPtrs); + VPtrInfoVector *VFPtrs = new VPtrInfoVector(); + computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs); + VFPtrLocations[RD] = VFPtrs; MethodVFTableLocationsTy NewMethodLocations; - for (VFPtrListTy::iterator I = VFPtrs.begin(), E = VFPtrs.end(); + for (VPtrInfoVector::iterator I = VFPtrs->begin(), E = VFPtrs->end(); I != E; ++I) { VFTableBuilder Builder(*this, RD, *I); - VFTableIdTy id(RD, I->VFPtrFullOffset); + VFTableIdTy id(RD, (*I)->FullOffsetInMDC); assert(VFTableLayouts.count(id) == 0); SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks( Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); VFTableLayouts[id] = new VTableLayout( Builder.getNumVTableComponents(), Builder.vtable_component_begin(), VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true); - NewMethodLocations.insert(Builder.vtable_indices_begin(), - Builder.vtable_indices_end()); Thunks.insert(Builder.thunks_begin(), Builder.thunks_end()); + + for (const auto &Loc : Builder.vtable_locations()) { + GlobalDecl GD = Loc.first; + MethodVFTableLocation NewLoc = Loc.second; + auto M = NewMethodLocations.find(GD); + if (M == NewMethodLocations.end() || NewLoc < M->second) + NewMethodLocations[GD] = NewLoc; + } } MethodVFTableLocations.insert(NewMethodLocations.begin(), @@ -3324,8 +3364,10 @@ void MicrosoftVTableContext::dumpMethodLocations( // Print the vtable indices for all the member functions. if (!IndicesMap.empty()) { Out << "VFTable indices for "; - Out << "'" << RD->getQualifiedNameAsString(); - Out << "' (" << IndicesMap.size() << " entries).\n"; + Out << "'"; + RD->printQualifiedName(Out); + Out << "' (" << IndicesMap.size() + << (IndicesMap.size() == 1 ? " entry" : " entries") << ").\n"; CharUnits LastVFPtrOffset = CharUnits::fromQuantity(-1); uint64_t LastVBIndex = 0; @@ -3352,49 +3394,66 @@ void MicrosoftVTableContext::dumpMethodLocations( } Out << '\n'; } + + Out.flush(); } -void MicrosoftVTableContext::computeVBTableRelatedInformation( +const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation( const CXXRecordDecl *RD) { - if (ComputedVBTableIndices.count(RD)) - return; - ComputedVBTableIndices.insert(RD); + VirtualBaseInfo *VBI; - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - BasesSetVectorTy VisitedBases; + { + // Get or create a VBI for RD. Don't hold a reference to the DenseMap cell, + // as it may be modified and rehashed under us. + VirtualBaseInfo *&Entry = VBaseInfo[RD]; + if (Entry) + return Entry; + Entry = VBI = new VirtualBaseInfo(); + } + + computeVTablePaths(/*ForVBTables=*/true, RD, VBI->VBPtrPaths); // First, see if the Derived class shared the vbptr with a non-virtual base. + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); if (const CXXRecordDecl *VBPtrBase = Layout.getBaseSharingVBPtr()) { - // If the Derived class shares the vbptr with a non-virtual base, - // it inherits its vbase indices. - computeVBTableRelatedInformation(VBPtrBase); - for (CXXRecordDecl::base_class_const_iterator I = VBPtrBase->vbases_begin(), - E = VBPtrBase->vbases_end(); I != E; ++I) { - const CXXRecordDecl *SubVBase = I->getType()->getAsCXXRecordDecl(); - assert(VBTableIndices.count(ClassPairTy(VBPtrBase, SubVBase))); - VBTableIndices[ClassPairTy(RD, SubVBase)] = - VBTableIndices[ClassPairTy(VBPtrBase, SubVBase)]; - VisitedBases.insert(SubVBase); - } + // If the Derived class shares the vbptr with a non-virtual base, the shared + // virtual bases come first so that the layout is the same. + const VirtualBaseInfo *BaseInfo = + computeVBTableRelatedInformation(VBPtrBase); + VBI->VBTableIndices.insert(BaseInfo->VBTableIndices.begin(), + BaseInfo->VBTableIndices.end()); } // New vbases are added to the end of the vbtable. // Skip the self entry and vbases visited in the non-virtual base, if any. - unsigned VBTableIndex = 1 + VisitedBases.size(); - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { - const CXXRecordDecl *CurVBase = I->getType()->getAsCXXRecordDecl(); - if (VisitedBases.insert(CurVBase)) - VBTableIndices[ClassPairTy(RD, CurVBase)] = VBTableIndex++; + unsigned VBTableIndex = 1 + VBI->VBTableIndices.size(); + for (const auto &VB : RD->vbases()) { + const CXXRecordDecl *CurVBase = VB.getType()->getAsCXXRecordDecl(); + if (!VBI->VBTableIndices.count(CurVBase)) + VBI->VBTableIndices[CurVBase] = VBTableIndex++; } + + return VBI; +} + +unsigned MicrosoftVTableContext::getVBTableIndex(const CXXRecordDecl *Derived, + const CXXRecordDecl *VBase) { + const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived); + assert(VBInfo->VBTableIndices.count(VBase)); + return VBInfo->VBTableIndices.find(VBase)->second; +} + +const VPtrInfoVector & +MicrosoftVTableContext::enumerateVBTables(const CXXRecordDecl *RD) { + return computeVBTableRelatedInformation(RD)->VBPtrPaths; } -const MicrosoftVTableContext::VFPtrListTy & +const VPtrInfoVector & MicrosoftVTableContext::getVFPtrOffsets(const CXXRecordDecl *RD) { computeVTableRelatedInformation(RD); assert(VFPtrLocations.count(RD) && "Couldn't find vfptr locations"); - return VFPtrLocations[RD]; + return *VFPtrLocations[RD]; } const VTableLayout & |