diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
45 files changed, 5890 insertions, 3616 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index fb96301..6438696 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -19,6 +19,7 @@ #include "clang/AST/Comment.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclContextInternals.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" @@ -327,7 +328,7 @@ const Decl *adjustDeclToTemplate(const Decl *D) { // FIXME: Adjust alias templates? return D; } -} // unnamed namespace +} // anonymous namespace const RawComment *ASTContext::getRawCommentForAnyRedecl( const Decl *D, @@ -366,8 +367,10 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( OriginalDeclForRC = I; RawCommentAndCacheFlags Raw; if (RC) { - Raw.setRaw(RC); + // Call order swapped to work around ICE in VS2015 RTM (Release Win32) + // https://connect.microsoft.com/VisualStudio/feedback/details/1741530 Raw.setKind(RawCommentAndCacheFlags::FromDecl); + Raw.setRaw(RC); } else Raw.setKind(RawCommentAndCacheFlags::NoCommentInDecl); Raw.setOriginalDecl(I); @@ -428,7 +431,6 @@ comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC, new (*this) comments::FullComment(FC->getBlocks(), ThisDeclInfo); return CFC; - } comments::FullComment *ASTContext::getLocalCommentForDeclUncached(const Decl *D) const { @@ -659,8 +661,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( nullptr, TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(), - CanonParams.data(), - CanonParams.size(), + CanonParams, SourceLocation())); // Get the new insert position for the node we care about. @@ -681,9 +682,11 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { case TargetCXXABI::GenericARM: // Same as Itanium at this level case TargetCXXABI::iOS: case TargetCXXABI::iOS64: + case TargetCXXABI::WatchOS: case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericMIPS: case TargetCXXABI::GenericItanium: + case TargetCXXABI::WebAssembly: return CreateItaniumCXXABI(*this); case TargetCXXABI::Microsoft: return CreateMicrosoftCXXABI(*this); @@ -732,19 +735,20 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, SubstTemplateTemplateParmPacks(this_()), GlobalNestedNameSpecifier(nullptr), Int128Decl(nullptr), UInt128Decl(nullptr), Float128StubDecl(nullptr), - BuiltinVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), - ObjCClassDecl(nullptr), ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr), + BuiltinVaListDecl(nullptr), BuiltinMSVaListDecl(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), FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr), - SourceMgr(SM), LangOpts(LOpts), + MakeIntegerSeqDecl(nullptr), SourceMgr(SM), LangOpts(LOpts), SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)), - AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts), - Idents(idents), Selectors(sels), BuiltinInfo(builtins), - DeclarationNames(*this), ExternalSource(nullptr), Listener(nullptr), - Comments(SM), CommentsLoaded(false), + AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr), + PrintingPolicy(LOpts), Idents(idents), Selectors(sels), + BuiltinInfo(builtins), DeclarationNames(*this), ExternalSource(nullptr), + Listener(nullptr), Comments(SM), CommentsLoaded(false), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(nullptr, 0) { TUDecl = TranslationUnitDecl::Create(*this); } @@ -757,10 +761,8 @@ ASTContext::~ASTContext() { ReleaseDeclContextMaps(); // Call all of the deallocation functions on all of their targets. - for (DeallocationMap::const_iterator I = Deallocations.begin(), - E = Deallocations.end(); I != E; ++I) - for (unsigned J = 0, N = I->second.size(); J != N; ++J) - (I->first)((I->second)[J]); + for (auto &Pair : Deallocations) + (Pair.first)(Pair.second); // ASTRecordLayout objects in ASTRecordLayouts must always be destroyed // because they can contain DenseMaps. @@ -783,23 +785,33 @@ ASTContext::~ASTContext() { A != AEnd; ++A) A->second->~AttrVec(); + for (std::pair<const MaterializeTemporaryExpr *, APValue *> &MTVPair : + MaterializedTemporaryValues) + MTVPair.second->~APValue(); + llvm::DeleteContainerSeconds(MangleNumberingContexts); } void ASTContext::ReleaseParentMapEntries() { - if (!AllParents) return; - for (const auto &Entry : *AllParents) { + if (!PointerParents) return; + for (const auto &Entry : *PointerParents) { if (Entry.second.is<ast_type_traits::DynTypedNode *>()) { delete Entry.second.get<ast_type_traits::DynTypedNode *>(); - } else { - assert(Entry.second.is<ParentVector *>()); + } else if (Entry.second.is<ParentVector *>()) { + delete Entry.second.get<ParentVector *>(); + } + } + for (const auto &Entry : *OtherParents) { + if (Entry.second.is<ast_type_traits::DynTypedNode *>()) { + delete Entry.second.get<ast_type_traits::DynTypedNode *>(); + } else if (Entry.second.is<ParentVector *>()) { delete Entry.second.get<ParentVector *>(); } } } void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { - Deallocations[Callback].push_back(Data); + Deallocations.push_back({Callback, Data}); } void @@ -898,6 +910,24 @@ ExternCContextDecl *ASTContext::getExternCContextDecl() const { return ExternCContext; } +BuiltinTemplateDecl * +ASTContext::buildBuiltinTemplateDecl(BuiltinTemplateKind BTK, + const IdentifierInfo *II) const { + auto *BuiltinTemplate = BuiltinTemplateDecl::Create(*this, TUDecl, II, BTK); + BuiltinTemplate->setImplicit(); + TUDecl->addDecl(BuiltinTemplate); + + return BuiltinTemplate; +} + +BuiltinTemplateDecl * +ASTContext::getMakeIntegerSeqDecl() const { + if (!MakeIntegerSeqDecl) + MakeIntegerSeqDecl = buildBuiltinTemplateDecl(BTK__make_integer_seq, + getMakeIntegerSeqName()); + return MakeIntegerSeqDecl; +} + RecordDecl *ASTContext::buildImplicitRecord(StringRef Name, RecordDecl::TagKind TK) const { SourceLocation Loc; @@ -950,13 +980,15 @@ void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { Types.push_back(Ty); } -void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { +void ASTContext::InitBuiltinTypes(const TargetInfo &Target, + const TargetInfo *AuxTarget) { assert((!this->Target || this->Target == &Target) && "Incorrect target reinitialization"); assert(VoidTy.isNull() && "Context reinitialized?"); this->Target = &Target; - + this->AuxTarget = AuxTarget; + ABI.reset(createCXXABI(Target)); AddrSpaceMap = getAddressSpaceMap(Target, LangOpts); AddrSpaceMapMangling = isAddrSpaceMapManglingEnabled(Target, LangOpts); @@ -1043,6 +1075,10 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { // Placeholder type for builtin functions. InitBuiltinType(BuiltinFnTy, BuiltinType::BuiltinFn); + // Placeholder type for OMP array sections. + if (LangOpts.OpenMP) + InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection); + // C99 6.2.5p11. FloatComplexTy = getComplexType(FloatTy); DoubleComplexTy = getComplexType(DoubleTy); @@ -1059,10 +1095,21 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { InitBuiltinType(OCLImage1dBufferTy, BuiltinType::OCLImage1dBuffer); InitBuiltinType(OCLImage2dTy, BuiltinType::OCLImage2d); InitBuiltinType(OCLImage2dArrayTy, BuiltinType::OCLImage2dArray); + InitBuiltinType(OCLImage2dDepthTy, BuiltinType::OCLImage2dDepth); + InitBuiltinType(OCLImage2dArrayDepthTy, BuiltinType::OCLImage2dArrayDepth); + InitBuiltinType(OCLImage2dMSAATy, BuiltinType::OCLImage2dMSAA); + InitBuiltinType(OCLImage2dArrayMSAATy, BuiltinType::OCLImage2dArrayMSAA); + InitBuiltinType(OCLImage2dMSAADepthTy, BuiltinType::OCLImage2dMSAADepth); + InitBuiltinType(OCLImage2dArrayMSAADepthTy, + BuiltinType::OCLImage2dArrayMSAADepth); InitBuiltinType(OCLImage3dTy, BuiltinType::OCLImage3d); InitBuiltinType(OCLSamplerTy, BuiltinType::OCLSampler); InitBuiltinType(OCLEventTy, BuiltinType::OCLEvent); + InitBuiltinType(OCLClkEventTy, BuiltinType::OCLClkEvent); + InitBuiltinType(OCLQueueTy, BuiltinType::OCLQueue); + InitBuiltinType(OCLNDRangeTy, BuiltinType::OCLNDRange); + InitBuiltinType(OCLReserveIDTy, BuiltinType::OCLReserveID); } // Builtin type for __objc_yes and __objc_no @@ -1083,7 +1130,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { InitBuiltinType(HalfTy, BuiltinType::Half); // Builtin type used to help define __builtin_va_list. - VaListTagTy = QualType(); + VaListTagDecl = nullptr; } DiagnosticsEngine &ASTContext::getDiagnostics() const { @@ -1629,11 +1676,21 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = Target->getIntAlign(); break; case BuiltinType::OCLEvent: + case BuiltinType::OCLClkEvent: + case BuiltinType::OCLQueue: + case BuiltinType::OCLNDRange: + case BuiltinType::OCLReserveID: case BuiltinType::OCLImage1d: case BuiltinType::OCLImage1dArray: case BuiltinType::OCLImage1dBuffer: case BuiltinType::OCLImage2d: case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage2dDepth: + case BuiltinType::OCLImage2dArrayDepth: + case BuiltinType::OCLImage2dMSAA: + case BuiltinType::OCLImage2dArrayMSAA: + case BuiltinType::OCLImage2dMSAADepth: + case BuiltinType::OCLImage2dArrayMSAADepth: case BuiltinType::OCLImage3d: // Currently these types are pointers to opaque types. Width = Target->getPointerWidth(0); @@ -1779,6 +1836,13 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = static_cast<unsigned>(Width); } } + break; + + case Type::Pipe: { + TypeInfo Info = getTypeInfo(cast<PipeType>(T)->getElementType()); + Width = Info.Width; + Align = Info.Align; + } } @@ -1861,7 +1925,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { /// getTargetDefaultAlignForAttributeAligned - Return the default alignment /// for __attribute__((aligned)) on this target, to be used if no alignment /// value is specified. -unsigned ASTContext::getTargetDefaultAlignForAttributeAligned(void) const { +unsigned ASTContext::getTargetDefaultAlignForAttributeAligned() const { return getTargetInfo().getDefaultAlignForAttributeAligned(); } @@ -2006,6 +2070,17 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, ObjCImpls[CatD] = ImplD; } +const ObjCMethodDecl * +ASTContext::getObjCMethodRedeclaration(const ObjCMethodDecl *MD) const { + return ObjCMethodRedecls.lookup(MD); +} + +void ASTContext::setObjCMethodRedeclaration(const ObjCMethodDecl *MD, + const ObjCMethodDecl *Redecl) { + assert(!getObjCMethodRedeclaration(MD) && "MD already has a redeclaration"); + ObjCMethodRedecls[MD] = Redecl; +} + const ObjCInterfaceDecl *ASTContext::getObjContainingInterface( const NamedDecl *ND) const { if (const ObjCInterfaceDecl *ID = @@ -2595,6 +2670,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { case Type::FunctionProto: case Type::BlockPointer: case Type::MemberPointer: + case Type::Pipe: return type; // These types can be variably-modified. All these modifications @@ -2759,9 +2835,10 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, QualType canon = getQualifiedType(QualType(canonTy,0), canonElementType.Quals); - // If we didn't need extra canonicalization for the element type, - // then just use that as our result. - if (QualType(canonElementType.Ty, 0) == elementType) + // If we didn't need extra canonicalization for the element type or the size + // expression, then just use that as our result. + if (QualType(canonElementType.Ty, 0) == elementType && + canonTy->getSizeExpr() == numElements) return canon; // Otherwise, we need to build a type which follows the spelling @@ -2956,6 +3033,21 @@ static bool isCanonicalResultType(QualType T) { T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone); } +CanQualType +ASTContext::getCanonicalFunctionResultType(QualType ResultType) const { + CanQualType CanResultType = getCanonicalType(ResultType); + + // Canonical result types do not have ARC lifetime qualifiers. + if (CanResultType.getQualifiers().hasObjCLifetime()) { + Qualifiers Qs = CanResultType.getQualifiers(); + Qs.removeObjCLifetime(); + return CanQualType::CreateUnsafe( + getQualifiedType(CanResultType.getUnqualifiedType(), Qs)); + } + + return CanResultType; +} + QualType ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, const FunctionProtoType::ExtProtoInfo &EPI) const { @@ -2993,14 +3085,8 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, CanonicalEPI.HasTrailingReturn = false; CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); - // Result types do not have ARC lifetime qualifiers. - QualType CanResultTy = getCanonicalType(ResultTy); - if (ResultTy.getQualifiers().hasObjCLifetime()) { - Qualifiers Qs = CanResultTy.getQualifiers(); - Qs.removeObjCLifetime(); - CanResultTy = getQualifiedType(CanResultTy.getUnqualifiedType(), Qs); - } - + // Adjust the canonical function result type. + CanQualType CanResultTy = getCanonicalFunctionResultType(ResultTy); Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI); // Get the new insert position for the node we care about. @@ -3039,6 +3125,32 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, return QualType(FTP, 0); } +/// Return pipe type for the specified type. +QualType ASTContext::getPipeType(QualType T) const { + llvm::FoldingSetNodeID ID; + PipeType::Profile(ID, T); + + void *InsertPos = 0; + if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(PT, 0); + + // If the pipe element type isn't canonical, this won't be a canonical type + // either, so fill in the canonical type field. + QualType Canonical; + if (!T.isCanonical()) { + Canonical = getPipeType(getCanonicalType(T)); + + // Get the new insert position for the node we care about. + PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!NewIP && "Shouldn't be in the map!"); + (void)NewIP; + } + PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical); + Types.push_back(New); + PipeTypes.InsertNode(New, InsertPos); + return QualType(New, 0); +} + #ifndef NDEBUG static bool NeedsInjectedClassNameType(const RecordDecl *D) { if (!isa<CXXRecordDecl>(D)) return false; @@ -3164,7 +3276,6 @@ QualType ASTContext::getAttributedType(AttributedType::Kind attrKind, return QualType(type, 0); } - /// \brief Retrieve a substitution-result type. QualType ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, @@ -3581,34 +3692,31 @@ static int CmpProtocolNames(ObjCProtocolDecl *const *LHS, return DeclarationName::compare((*LHS)->getDeclName(), (*RHS)->getDeclName()); } -static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols, - unsigned NumProtocols) { - if (NumProtocols == 0) return true; +static bool areSortedAndUniqued(ArrayRef<ObjCProtocolDecl *> Protocols) { + if (Protocols.empty()) return true; if (Protocols[0]->getCanonicalDecl() != Protocols[0]) return false; - for (unsigned i = 1; i != NumProtocols; ++i) + for (unsigned i = 1; i != Protocols.size(); ++i) if (CmpProtocolNames(&Protocols[i - 1], &Protocols[i]) >= 0 || Protocols[i]->getCanonicalDecl() != Protocols[i]) return false; return true; } -static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols, - unsigned &NumProtocols) { - ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols; - +static void +SortAndUniqueProtocols(SmallVectorImpl<ObjCProtocolDecl *> &Protocols) { // Sort protocols, keyed by name. - llvm::array_pod_sort(Protocols, ProtocolsEnd, CmpProtocolNames); + llvm::array_pod_sort(Protocols.begin(), Protocols.end(), CmpProtocolNames); // Canonicalize. - for (unsigned I = 0, N = NumProtocols; I != N; ++I) - Protocols[I] = Protocols[I]->getCanonicalDecl(); - + for (ObjCProtocolDecl *&P : Protocols) + P = P->getCanonicalDecl(); + // Remove duplicates. - ProtocolsEnd = std::unique(Protocols, ProtocolsEnd); - NumProtocols = ProtocolsEnd-Protocols; + auto ProtocolsEnd = std::unique(Protocols.begin(), Protocols.end()); + Protocols.erase(ProtocolsEnd, Protocols.end()); } QualType ASTContext::getObjCObjectType(QualType BaseType, @@ -3655,8 +3763,7 @@ QualType ASTContext::getObjCObjectType( [&](QualType type) { return type.isCanonical(); }); - bool protocolsSorted = areSortedAndUniqued(protocols.data(), - protocols.size()); + bool protocolsSorted = areSortedAndUniqued(protocols); if (!typeArgsAreCanonical || !protocolsSorted || !baseType.isCanonical()) { // Determine the canonical type arguments. ArrayRef<QualType> canonTypeArgs; @@ -3673,12 +3780,9 @@ QualType ASTContext::getObjCObjectType( ArrayRef<ObjCProtocolDecl *> canonProtocols; SmallVector<ObjCProtocolDecl*, 8> canonProtocolsVec; if (!protocolsSorted) { - canonProtocolsVec.insert(canonProtocolsVec.begin(), - protocols.begin(), - protocols.end()); - unsigned uniqueCount = protocols.size(); - SortAndUniqueProtocols(&canonProtocolsVec[0], uniqueCount); - canonProtocols = llvm::makeArrayRef(&canonProtocolsVec[0], uniqueCount); + canonProtocolsVec.append(protocols.begin(), protocols.end()); + SortAndUniqueProtocols(canonProtocolsVec); + canonProtocols = canonProtocolsVec; } else { canonProtocols = protocols; } @@ -3869,7 +3973,6 @@ QualType ASTContext::getTypeOfType(QualType tofType) const { return QualType(tot, 0); } - /// \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 @@ -3921,20 +4024,20 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType, /// getAutoType - Return the uniqued reference to the 'auto' type which has been /// deduced to the given type, or to the canonical undeduced 'auto' type, or the /// canonical deduced-but-dependent 'auto' type. -QualType ASTContext::getAutoType(QualType DeducedType, bool IsDecltypeAuto, +QualType ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent) const { - if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent) + if (DeducedType.isNull() && Keyword == AutoTypeKeyword::Auto && !IsDependent) return getAutoDeductType(); // Look in the folding set for an existing type. void *InsertPos = nullptr; llvm::FoldingSetNodeID ID; - AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent); + AutoType::Profile(ID, DeducedType, Keyword, IsDependent); if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(AT, 0); AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType, - IsDecltypeAuto, + Keyword, IsDependent); Types.push_back(AT); if (InsertPos) @@ -3974,7 +4077,7 @@ QualType ASTContext::getAtomicType(QualType T) const { QualType ASTContext::getAutoDeductType() const { if (AutoDeductTy.isNull()) AutoDeductTy = QualType( - new (*this, TypeAlignment) AutoType(QualType(), /*decltype(auto)*/false, + new (*this, TypeAlignment) AutoType(QualType(), AutoTypeKeyword::Auto, /*dependent*/false), 0); return AutoDeductTy; @@ -4310,7 +4413,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { A != AEnd; (void)++A, ++Idx) CanonArgs[Idx] = getCanonicalTemplateArgument(*A); - return TemplateArgument(CanonArgs, Arg.pack_size()); + return TemplateArgument(llvm::makeArrayRef(CanonArgs, Arg.pack_size())); } } @@ -4374,7 +4477,6 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } - const ArrayType *ASTContext::getAsArrayType(QualType T) const { // Handle the non-qualified case efficiently. if (!T.hasLocalQualifiers()) { @@ -4909,8 +5011,6 @@ bool ASTContext::BlockRequiresCopying(QualType Ty, // If we have lifetime, that dominates. if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) { - assert(getLangOpts().ObjCAutoRefCount); - switch (lifetime) { case Qualifiers::OCL_None: llvm_unreachable("impossible"); @@ -4944,14 +5044,14 @@ bool ASTContext::getByrefLifetime(QualType Ty, if (Ty->isRecordType()) { HasByrefExtendedLayout = true; LifeTime = Qualifiers::OCL_None; - } - else if (getLangOpts().ObjCAutoRefCount) - LifeTime = Ty.getObjCLifetime(); - // MRR. - else if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType()) + } else if ((LifeTime = Ty.getObjCLifetime())) { + // Honor the ARC qualifiers. + } else if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType()) { + // The MRR rule. LifeTime = Qualifiers::OCL_ExplicitNone; - else + } else { LifeTime = Qualifiers::OCL_None; + } return true; } @@ -4990,9 +5090,10 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const { } bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const { - return getLangOpts().MSVCCompat && VD->isStaticDataMember() && + return getTargetInfo().getCXXABI().isMicrosoft() && + VD->isStaticDataMember() && VD->getType()->isIntegralOrEnumerationType() && - VD->isFirstDecl() && !VD->isOutOfLine() && VD->hasInit(); + !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit(); } static inline @@ -5364,8 +5465,18 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C, case BuiltinType::OCLImage1dBuffer: case BuiltinType::OCLImage2d: case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage2dDepth: + case BuiltinType::OCLImage2dArrayDepth: + case BuiltinType::OCLImage2dMSAA: + case BuiltinType::OCLImage2dArrayMSAA: + case BuiltinType::OCLImage2dMSAADepth: + case BuiltinType::OCLImage2dArrayMSAADepth: case BuiltinType::OCLImage3d: case BuiltinType::OCLEvent: + case BuiltinType::OCLClkEvent: + case BuiltinType::OCLQueue: + case BuiltinType::OCLNDRange: + case BuiltinType::OCLReserveID: case BuiltinType::OCLSampler: case BuiltinType::Dependent: #define BUILTIN_TYPE(KIND, ID) @@ -5779,8 +5890,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Just ignore it. case Type::Auto: return; - + case Type::Pipe: #define ABSTRACT_TYPE(KIND, BASE) #define TYPE(KIND, BASE) #define DEPENDENT_TYPE(KIND, BASE) \ @@ -5998,10 +6109,19 @@ ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const { // __builtin_va_list Construction Functions //===----------------------------------------------------------------------===// -static TypedefDecl *CreateCharPtrBuiltinVaListDecl(const ASTContext *Context) { - // typedef char* __builtin_va_list; +static TypedefDecl *CreateCharPtrNamedVaListDecl(const ASTContext *Context, + StringRef Name) { + // typedef char* __builtin[_ms]_va_list; QualType T = Context->getPointerType(Context->CharTy); - return Context->buildImplicitTypedef(T, "__builtin_va_list"); + return Context->buildImplicitTypedef(T, Name); +} + +static TypedefDecl *CreateMSVaListDecl(const ASTContext *Context) { + return CreateCharPtrNamedVaListDecl(Context, "__builtin_ms_va_list"); +} + +static TypedefDecl *CreateCharPtrBuiltinVaListDecl(const ASTContext *Context) { + return CreateCharPtrNamedVaListDecl(Context, "__builtin_va_list"); } static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) { @@ -6067,8 +6187,8 @@ CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { VaListTagDecl->addDecl(Field); } VaListTagDecl->completeDefinition(); + Context->VaListTagDecl = VaListTagDecl; QualType VaListTagType = Context->getRecordType(VaListTagDecl); - Context->VaListTagTy = VaListTagType; // } __builtin_va_list; return Context->buildImplicitTypedef(VaListTagType, "__builtin_va_list"); @@ -6119,8 +6239,8 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { VaListTagDecl->addDecl(Field); } VaListTagDecl->completeDefinition(); + Context->VaListTagDecl = VaListTagDecl; QualType VaListTagType = Context->getRecordType(VaListTagDecl); - Context->VaListTagTy = VaListTagType; // } __va_list_tag; TypedefDecl *VaListTagTypedefDecl = @@ -6139,7 +6259,7 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { static TypedefDecl * CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { - // typedef struct __va_list_tag { + // struct __va_list_tag { RecordDecl *VaListTagDecl; VaListTagDecl = Context->buildImplicitRecord("__va_list_tag"); VaListTagDecl->startDefinition(); @@ -6179,21 +6299,15 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { VaListTagDecl->addDecl(Field); } VaListTagDecl->completeDefinition(); + Context->VaListTagDecl = VaListTagDecl; QualType VaListTagType = Context->getRecordType(VaListTagDecl); - Context->VaListTagTy = VaListTagType; - // } __va_list_tag; - TypedefDecl *VaListTagTypedefDecl = - Context->buildImplicitTypedef(VaListTagType, "__va_list_tag"); - - QualType VaListTagTypedefType = - Context->getTypedefType(VaListTagTypedefDecl); + // }; - // typedef __va_list_tag __builtin_va_list[1]; + // typedef struct __va_list_tag __builtin_va_list[1]; llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1); - QualType VaListTagArrayType - = Context->getConstantArrayType(VaListTagTypedefType, - Size, ArrayType::Normal,0); + QualType VaListTagArrayType = + Context->getConstantArrayType(VaListTagType, Size, ArrayType::Normal, 0); return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list"); } @@ -6248,7 +6362,7 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { static TypedefDecl * CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { - // typedef struct __va_list_tag { + // struct __va_list_tag { RecordDecl *VaListTagDecl; VaListTagDecl = Context->buildImplicitRecord("__va_list_tag"); VaListTagDecl->startDefinition(); @@ -6288,20 +6402,15 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { VaListTagDecl->addDecl(Field); } VaListTagDecl->completeDefinition(); + Context->VaListTagDecl = VaListTagDecl; QualType VaListTagType = Context->getRecordType(VaListTagDecl); - Context->VaListTagTy = VaListTagType; - // } __va_list_tag; - TypedefDecl *VaListTagTypedefDecl = - Context->buildImplicitTypedef(VaListTagType, "__va_list_tag"); - QualType VaListTagTypedefType = - Context->getTypedefType(VaListTagTypedefDecl); + // }; // typedef __va_list_tag __builtin_va_list[1]; llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1); - QualType VaListTagArrayType - = Context->getConstantArrayType(VaListTagTypedefType, - Size, ArrayType::Normal,0); + QualType VaListTagArrayType = + Context->getConstantArrayType(VaListTagType, Size, ArrayType::Normal, 0); return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list"); } @@ -6339,13 +6448,20 @@ TypedefDecl *ASTContext::getBuiltinVaListDecl() const { return BuiltinVaListDecl; } -QualType ASTContext::getVaListTagType() const { - // Force the creation of VaListTagTy by building the __builtin_va_list +Decl *ASTContext::getVaListTagDecl() const { + // Force the creation of VaListTagDecl by building the __builtin_va_list // declaration. - if (VaListTagTy.isNull()) - (void) getBuiltinVaListDecl(); + if (!VaListTagDecl) + (void)getBuiltinVaListDecl(); - return VaListTagTy; + return VaListTagDecl; +} + +TypedefDecl *ASTContext::getBuiltinMSVaListDecl() const { + if (!BuiltinMSVaListDecl) + BuiltinMSVaListDecl = CreateMSVaListDecl(this); + + return BuiltinMSVaListDecl; } void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) { @@ -7711,6 +7827,24 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return QualType(); } + case Type::Pipe: + { + // Merge two pointer types, while trying to preserve typedef info + QualType LHSValue = LHS->getAs<PipeType>()->getElementType(); + QualType RHSValue = RHS->getAs<PipeType>()->getElementType(); + if (Unqualified) { + LHSValue = LHSValue.getUnqualifiedType(); + RHSValue = RHSValue.getUnqualifiedType(); + } + QualType ResultType = mergeTypes(LHSValue, RHSValue, false, + Unqualified); + if (ResultType.isNull()) return QualType(); + if (getCanonicalType(LHSValue) == getCanonicalType(ResultType)) + return LHS; + if (getCanonicalType(RHSValue) == getCanonicalType(ResultType)) + return RHS; + return getPipeType(ResultType); + } } llvm_unreachable("Invalid Type::Class!"); @@ -7734,6 +7868,10 @@ bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs( return true; } +void ASTContext::ResetObjCLayout(const ObjCContainerDecl *CD) { + ObjCLayouts[CD] = nullptr; +} + /// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and /// 'RHS' attributes and returns the merged version; including for function /// return types. @@ -8128,7 +8266,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, QualType ASTContext::GetBuiltinType(unsigned Id, GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs) const { - const char *TypeStr = BuiltinInfo.GetTypeString(Id); + const char *TypeStr = BuiltinInfo.getTypeString(Id); SmallVector<QualType, 8> ArgTypes; @@ -8212,7 +8350,8 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, if (!FD->isInlined()) return External; - if ((!Context.getLangOpts().CPlusPlus && !Context.getLangOpts().MSVCCompat && + if ((!Context.getLangOpts().CPlusPlus && + !Context.getTargetInfo().getCXXABI().isMicrosoft() && !FD->hasAttr<DLLExportAttr>()) || FD->hasAttr<GNUInlineAttr>()) { // FIXME: This doesn't match gcc's behavior for dllexport inline functions. @@ -8235,13 +8374,13 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, return GVA_DiscardableODR; } -static GVALinkage adjustGVALinkageForDLLAttribute(GVALinkage L, const Decl *D) { +static GVALinkage adjustGVALinkageForAttributes(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>()) { + } else if (D->hasAttr<DLLExportAttr>() || D->hasAttr<CUDAGlobalAttr>()) { if (L == GVA_DiscardableODR) return GVA_StrongODR; } @@ -8249,8 +8388,8 @@ static GVALinkage adjustGVALinkageForDLLAttribute(GVALinkage L, const Decl *D) { } GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { - return adjustGVALinkageForDLLAttribute(basicGVALinkageForFunction(*this, FD), - FD); + return adjustGVALinkageForAttributes(basicGVALinkageForFunction(*this, FD), + FD); } static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, @@ -8285,9 +8424,14 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, switch (VD->getTemplateSpecializationKind()) { case TSK_Undeclared: - case TSK_ExplicitSpecialization: return GVA_StrongExternal; + case TSK_ExplicitSpecialization: + return Context.getTargetInfo().getCXXABI().isMicrosoft() && + VD->isStaticDataMember() + ? GVA_StrongODR + : GVA_StrongExternal; + case TSK_ExplicitInstantiationDefinition: return GVA_StrongODR; @@ -8302,8 +8446,8 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, } GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { - return adjustGVALinkageForDLLAttribute(basicGVALinkageForVariable(*this, VD), - VD); + return adjustGVALinkageForAttributes(basicGVALinkageForVariable(*this, VD), + VD); } bool ASTContext::DeclMustBeEmitted(const Decl *D) { @@ -8313,6 +8457,9 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // Global named register variables (GNU extension) are never emitted. if (VD->getStorageClass() == SC_Register) return false; + if (VD->getDescribedVarTemplate() || + isa<VarTemplatePartialSpecializationDecl>(VD)) + 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) @@ -8385,7 +8532,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return true; // Variables that have initialization with side-effects are required. - if (VD->getInit() && VD->getInit()->HasSideEffects(*this)) + if (VD->getInit() && VD->getInit()->HasSideEffects(*this) && + !VD->evaluateValue()) return true; return false; @@ -8425,6 +8573,8 @@ MangleContext *ASTContext::createMangleContext() { case TargetCXXABI::GenericMIPS: case TargetCXXABI::iOS: case TargetCXXABI::iOS64: + case TargetCXXABI::WebAssembly: + case TargetCXXABI::WatchOS: return ItaniumMangleContext::create(*this, getDiagnostics()); case TargetCXXABI::Microsoft: return MicrosoftMangleContext::create(*this, getDiagnostics()); @@ -8543,6 +8693,25 @@ Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx); } +void ASTContext::addTypedefNameForUnnamedTagDecl(TagDecl *TD, + TypedefNameDecl *DD) { + return ABI->addTypedefNameForUnnamedTagDecl(TD, DD); +} + +TypedefNameDecl * +ASTContext::getTypedefNameForUnnamedTagDecl(const TagDecl *TD) { + return ABI->getTypedefNameForUnnamedTagDecl(TD); +} + +void ASTContext::addDeclaratorForUnnamedTagDecl(TagDecl *TD, + DeclaratorDecl *DD) { + return ABI->addDeclaratorForUnnamedTagDecl(TD, DD); +} + +DeclaratorDecl *ASTContext::getDeclaratorForUnnamedTagDecl(const TagDecl *TD) { + return ABI->getDeclaratorForUnnamedTagDecl(TD); +} + void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) { ParamIndices[D] = index; } @@ -8559,12 +8728,14 @@ ASTContext::getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, bool MayCreate) { assert(E && E->getStorageDuration() == SD_Static && "don't need to cache the computed value for this temporary"); - if (MayCreate) - return &MaterializedTemporaryValues[E]; + if (MayCreate) { + APValue *&MTVI = MaterializedTemporaryValues[E]; + if (!MTVI) + MTVI = new (*this) APValue; + return MTVI; + } - llvm::DenseMap<const MaterializeTemporaryExpr *, APValue>::iterator I = - MaterializedTemporaryValues.find(E); - return I == MaterializedTemporaryValues.end() ? nullptr : &I->second; + return MaterializedTemporaryValues.lookup(E); } bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { @@ -8587,6 +8758,32 @@ bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { namespace { +ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap( + ASTContext::ParentMapPointers::mapped_type U) { + if (const auto *D = U.dyn_cast<const Decl *>()) + return ast_type_traits::DynTypedNode::create(*D); + if (const auto *S = U.dyn_cast<const Stmt *>()) + return ast_type_traits::DynTypedNode::create(*S); + return *U.get<ast_type_traits::DynTypedNode *>(); +} + +/// Template specializations to abstract away from pointers and TypeLocs. +/// @{ +template <typename T> +ast_type_traits::DynTypedNode createDynTypedNode(const T &Node) { + return ast_type_traits::DynTypedNode::create(*Node); +} +template <> +ast_type_traits::DynTypedNode createDynTypedNode(const TypeLoc &Node) { + return ast_type_traits::DynTypedNode::create(Node); +} +template <> +ast_type_traits::DynTypedNode +createDynTypedNode(const NestedNameSpecifierLoc &Node) { + return ast_type_traits::DynTypedNode::create(Node); +} +/// @} + /// \brief A \c RecursiveASTVisitor that builds a map from nodes to their /// parents as defined by the \c RecursiveASTVisitor. /// @@ -8596,22 +8793,25 @@ namespace { /// /// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes. class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> { - public: /// \brief Builds and returns the translation unit's parent map. /// /// The caller takes ownership of the returned \c ParentMap. - static ASTContext::ParentMap *buildMap(TranslationUnitDecl &TU) { - ParentMapASTVisitor Visitor(new ASTContext::ParentMap); + static std::pair<ASTContext::ParentMapPointers *, + ASTContext::ParentMapOtherNodes *> + buildMap(TranslationUnitDecl &TU) { + ParentMapASTVisitor Visitor(new ASTContext::ParentMapPointers, + new ASTContext::ParentMapOtherNodes); Visitor.TraverseDecl(&TU); - return Visitor.Parents; + return std::make_pair(Visitor.Parents, Visitor.OtherParents); } private: typedef RecursiveASTVisitor<ParentMapASTVisitor> VisitorBase; - ParentMapASTVisitor(ASTContext::ParentMap *Parents) : Parents(Parents) { - } + ParentMapASTVisitor(ASTContext::ParentMapPointers *Parents, + ASTContext::ParentMapOtherNodes *OtherParents) + : Parents(Parents), OtherParents(OtherParents) {} bool shouldVisitTemplateInstantiations() const { return true; @@ -8619,14 +8819,11 @@ namespace { bool shouldVisitImplicitCode() const { return true; } - // Disables data recursion. We intercept Traverse* methods in the RAV, which - // are not triggered during data recursion. - bool shouldUseDataRecursionFor(clang::Stmt *S) const { - return false; - } - template <typename T> - bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) { + template <typename T, typename MapNodeTy, typename BaseTraverseFn, + typename MapTy> + bool TraverseNode(T Node, MapNodeTy MapNode, + BaseTraverseFn BaseTraverse, MapTy *Parents) { if (!Node) return true; if (ParentStack.size() > 0) { @@ -8640,18 +8837,25 @@ namespace { // map. The main problem there is to implement hash functions / // comparison operators for all types that DynTypedNode supports that // do not have pointer identity. - auto &NodeOrVector = (*Parents)[Node]; + auto &NodeOrVector = (*Parents)[MapNode]; if (NodeOrVector.isNull()) { - NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back()); + if (const auto *D = ParentStack.back().get<Decl>()) + NodeOrVector = D; + else if (const auto *S = ParentStack.back().get<Stmt>()) + NodeOrVector = S; + else + 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); + if (!NodeOrVector.template is<ASTContext::ParentVector *>()) { + auto *Vector = new ASTContext::ParentVector( + 1, getSingleDynTypedNodeFromParentMap(NodeOrVector)); + if (auto *Node = + NodeOrVector + .template dyn_cast<ast_type_traits::DynTypedNode *>()) + delete Node; NodeOrVector = Vector; - delete Node; } - assert(NodeOrVector.template is<ASTContext::ParentVector *>()); auto *Vector = NodeOrVector.template get<ASTContext::ParentVector *>(); @@ -8666,47 +8870,74 @@ namespace { Vector->push_back(ParentStack.back()); } } - ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node)); - bool Result = (this ->* traverse) (Node); + ParentStack.push_back(createDynTypedNode(Node)); + bool Result = BaseTraverse(); ParentStack.pop_back(); return Result; } bool TraverseDecl(Decl *DeclNode) { - return TraverseNode(DeclNode, &VisitorBase::TraverseDecl); + return TraverseNode(DeclNode, DeclNode, + [&] { return VisitorBase::TraverseDecl(DeclNode); }, + Parents); } bool TraverseStmt(Stmt *StmtNode) { - return TraverseNode(StmtNode, &VisitorBase::TraverseStmt); + return TraverseNode(StmtNode, StmtNode, + [&] { return VisitorBase::TraverseStmt(StmtNode); }, + Parents); + } + + bool TraverseTypeLoc(TypeLoc TypeLocNode) { + return TraverseNode( + TypeLocNode, ast_type_traits::DynTypedNode::create(TypeLocNode), + [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); }, + OtherParents); } - ASTContext::ParentMap *Parents; + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) { + return TraverseNode( + NNSLocNode, ast_type_traits::DynTypedNode::create(NNSLocNode), + [&] { + return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); + }, + OtherParents); + } + + ASTContext::ParentMapPointers *Parents; + ASTContext::ParentMapOtherNodes *OtherParents; llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack; friend class RecursiveASTVisitor<ParentMapASTVisitor>; }; -} // end namespace +} // anonymous namespace + +template <typename NodeTy, typename MapTy> +static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node, + const MapTy &Map) { + auto I = Map.find(Node); + if (I == Map.end()) { + return llvm::ArrayRef<ast_type_traits::DynTypedNode>(); + } + if (auto *V = I->second.template dyn_cast<ASTContext::ParentVector *>()) { + return llvm::makeArrayRef(*V); + } + return getSingleDynTypedNodeFromParentMap(I->second); +} -ArrayRef<ast_type_traits::DynTypedNode> +ASTContext::DynTypedNodeList ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { - assert(Node.getMemoizationData() && - "Invariant broken: only nodes that support memoization may be " - "used in the parent map."); - if (!AllParents) { + if (!PointerParents) { // We always need to run over the whole translation unit, as // hasAncestor can escape any subtree. - AllParents.reset( - ParentMapASTVisitor::buildMap(*getTranslationUnitDecl())); - } - ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData()); - if (I == AllParents->end()) { - return None; - } - if (auto *N = I->second.dyn_cast<ast_type_traits::DynTypedNode *>()) { - return llvm::makeArrayRef(N, 1); + auto Maps = ParentMapASTVisitor::buildMap(*getTranslationUnitDecl()); + PointerParents.reset(Maps.first); + OtherParents.reset(Maps.second); } - return *I->second.get<ParentVector *>(); + if (Node.getNodeKind().hasPointerIdentity()) + return getDynNodeFromMap(Node.getMemoizationData(), *PointerParents); + return getDynNodeFromMap(Node, *OtherParents); } bool diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index dddaa5a..0ab1fa7 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -66,11 +66,63 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { continue; } - // Don't desugar template specializations, unless it's an alias template. - if (const TemplateSpecializationType *TST - = dyn_cast<TemplateSpecializationType>(Ty)) - if (!TST->isTypeAlias()) + // Desugar FunctionType if return type or any parameter type should be + // desugared. Preserve nullability attribute on desugared types. + if (const FunctionType *FT = dyn_cast<FunctionType>(Ty)) { + bool DesugarReturn = false; + QualType SugarRT = FT->getReturnType(); + QualType RT = Desugar(Context, SugarRT, DesugarReturn); + if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) { + RT = Context.getAttributedType( + AttributedType::getNullabilityAttrKind(*nullability), RT, RT); + } + + bool DesugarArgument = false; + SmallVector<QualType, 4> Args; + const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT); + if (FPT) { + for (QualType SugarPT : FPT->param_types()) { + QualType PT = Desugar(Context, SugarPT, DesugarArgument); + if (auto nullability = + AttributedType::stripOuterNullability(SugarPT)) { + PT = Context.getAttributedType( + AttributedType::getNullabilityAttrKind(*nullability), PT, PT); + } + Args.push_back(PT); + } + } + + if (DesugarReturn || DesugarArgument) { + ShouldAKA = true; + QT = FPT ? Context.getFunctionType(RT, Args, FPT->getExtProtoInfo()) + : Context.getFunctionNoProtoType(RT, FT->getExtInfo()); + break; + } + } + + // Desugar template specializations if any template argument should be + // desugared. + if (const TemplateSpecializationType *TST = + dyn_cast<TemplateSpecializationType>(Ty)) { + if (!TST->isTypeAlias()) { + bool DesugarArgument = false; + SmallVector<TemplateArgument, 4> Args; + for (unsigned I = 0, N = TST->getNumArgs(); I != N; ++I) { + const TemplateArgument &Arg = TST->getArg(I); + if (Arg.getKind() == TemplateArgument::Type) + Args.push_back(Desugar(Context, Arg.getAsType(), DesugarArgument)); + else + Args.push_back(Arg); + } + + if (DesugarArgument) { + ShouldAKA = true; + QT = Context.getTemplateSpecializationType( + TST->getTemplateName(), Args.data(), Args.size(), QT); + } break; + } + } // Don't desugar magic Objective-C types. if (QualType(Ty,0) == Context.getObjCIdType() || @@ -80,7 +132,8 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { break; // Don't desugar va_list. - if (QualType(Ty,0) == Context.getBuiltinVaListType()) + if (QualType(Ty, 0) == Context.getBuiltinVaListType() || + QualType(Ty, 0) == Context.getBuiltinMSVaListType()) break; // Otherwise, do a single-step desugar. @@ -393,8 +446,6 @@ void clang::FormatASTNodeDiagnosticArgument( } - OS.flush(); - if (NeedQuotes) { Output.insert(Output.begin()+OldEnd, '\''); Output.push_back('\''); diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp index c95922b..4622a75 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp @@ -21,8 +21,10 @@ #include "clang/AST/DeclVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeVisitor.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" +#include "clang/Sema/LocInfoType.h" #include "llvm/Support/raw_ostream.h" using namespace clang; using namespace clang::comments; @@ -447,6 +449,7 @@ namespace { const ClassTemplatePartialSpecializationDecl *D); void VisitClassScopeFunctionSpecializationDecl( const ClassScopeFunctionSpecializationDecl *D); + void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D); void VisitVarTemplateDecl(const VarTemplateDecl *D); void VisitVarTemplateSpecializationDecl( const VarTemplateSpecializationDecl *D); @@ -653,6 +656,15 @@ void ASTDumper::dumpTypeAsChild(const Type *T) { OS << "<<<NULL>>>"; return; } + if (const LocInfoType *LIT = llvm::dyn_cast<LocInfoType>(T)) { + { + ColorScope Color(*this, TypeColor); + OS << "LocInfo Type"; + } + dumpPointer(T); + dumpTypeAsChild(LIT->getTypeSourceInfo()->getType()); + return; + } { ColorScope Color(*this, TypeColor); @@ -1043,6 +1055,7 @@ void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) { dumpType(D->getUnderlyingType()); if (D->isModulePrivate()) OS << " __module_private__"; + dumpTypeAsChild(D->getUnderlyingType()); } void ASTDumper::VisitEnumDecl(const EnumDecl *D) { @@ -1214,6 +1227,7 @@ void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) { dumpName(D); dumpType(D->getUnderlyingType()); + dumpTypeAsChild(D->getUnderlyingType()); } void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { @@ -1333,6 +1347,11 @@ void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) { VisitTemplateDecl(D, false); } +void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); +} + void ASTDumper::VisitVarTemplateSpecializationDecl( const VarTemplateSpecializationDecl *D) { dumpTemplateArgumentList(D->getTemplateArgs()); @@ -1378,20 +1397,23 @@ void ASTDumper::VisitTemplateTemplateParmDecl( void ASTDumper::VisitUsingDecl(const UsingDecl *D) { OS << ' '; - D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + if (D->getQualifier()) + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); OS << D->getNameAsString(); } void ASTDumper::VisitUnresolvedUsingTypenameDecl( const UnresolvedUsingTypenameDecl *D) { OS << ' '; - D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + if (D->getQualifier()) + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); OS << D->getNameAsString(); } void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { OS << ' '; - D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + if (D->getQualifier()) + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); OS << D->getNameAsString(); dumpType(D->getType()); } @@ -1399,6 +1421,8 @@ void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { OS << ' '; dumpBareDeclRef(D->getTargetDecl()); + if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl())) + dumpTypeAsChild(TD->getTypeForDecl()); } void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { @@ -2017,6 +2041,9 @@ void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { VisitExpr(Node); dumpPointer(Node->getPack()); dumpName(Node->getPack()); + if (Node->isPartiallySubstituted()) + for (const auto &A : Node->getPartialArguments()) + dumpTemplateArgument(A); } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index 35c0f69..916f108 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -878,6 +878,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; } + case Type::Pipe: { + if (!IsStructurallyEquivalent(Context, + cast<PipeType>(T1)->getElementType(), + cast<PipeType>(T2)->getElementType())) + return false; + break; + } + } // end switch return true; @@ -1746,7 +1754,7 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) { return QualType(); } - return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto(), + return Importer.getToContext().getAutoType(ToDeduced, T->getKeyword(), /*IsDependent*/false); } @@ -2144,7 +2152,7 @@ TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList( return TemplateParameterList::Create(Importer.getToContext(), Importer.Import(Params->getTemplateLoc()), Importer.Import(Params->getLAngleLoc()), - ToParams.data(), ToParams.size(), + ToParams, Importer.Import(Params->getRAngleLoc())); } @@ -2210,11 +2218,9 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { ToPack.reserve(From.pack_size()); if (ImportTemplateArguments(From.pack_begin(), From.pack_size(), ToPack)) return TemplateArgument(); - - TemplateArgument *ToArgs - = new (Importer.getToContext()) TemplateArgument[ToPack.size()]; - std::copy(ToPack.begin(), ToPack.end(), ToArgs); - return TemplateArgument(ToArgs, ToPack.size()); + + return TemplateArgument( + llvm::makeArrayRef(ToPack).copy(Importer.getToContext())); } } @@ -4917,13 +4923,14 @@ Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { if (!ToBody && S->getBody()) return nullptr; SourceLocation ToForLoc = Importer.Import(S->getForLoc()); + SourceLocation ToCoawaitLoc = Importer.Import(S->getCoawaitLoc()); SourceLocation ToColonLoc = Importer.Import(S->getColonLoc()); SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc()); return new (Importer.getToContext()) CXXForRangeStmt(ToRange, ToBeginEnd, ToCond, ToInc, ToLoopVar, ToBody, - ToForLoc, ToColonLoc, - ToRParenLoc); + ToForLoc, ToCoawaitLoc, + ToColonLoc, ToRParenLoc); } Stmt *ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { @@ -5331,7 +5338,7 @@ Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) { return new (Importer.getToContext()) CallExpr(Importer.getToContext(), ToCallee, - ArrayRef<Expr*>(ToArgs_Copied, NumArgs), T, E->getValueKind(), + llvm::makeArrayRef(ToArgs_Copied, NumArgs), T, E->getValueKind(), Importer.Import(E->getRParenLoc())); } diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h index dad2264..c23b919 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h +++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h @@ -21,6 +21,7 @@ namespace clang { class ASTContext; class CXXConstructorDecl; +class DeclaratorDecl; class Expr; class MemberPointerType; class MangleNumberingContext; @@ -57,6 +58,17 @@ public: virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, unsigned ParmIdx) = 0; + + virtual void addTypedefNameForUnnamedTagDecl(TagDecl *TD, + TypedefNameDecl *DD) = 0; + + virtual TypedefNameDecl * + getTypedefNameForUnnamedTagDecl(const TagDecl *TD) = 0; + + virtual void addDeclaratorForUnnamedTagDecl(TagDecl *TD, + DeclaratorDecl *DD) = 0; + + virtual DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) = 0; }; /// Creates an instance of a C++ ABI class. diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index 800c8f8..6785a0c 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -31,16 +31,16 @@ void CXXBasePaths::ComputeDeclsFound() { Decls.insert(Path->Decls.front()); NumDeclsFound = Decls.size(); - DeclsFound = new NamedDecl * [NumDeclsFound]; - std::copy(Decls.begin(), Decls.end(), DeclsFound); + DeclsFound = llvm::make_unique<NamedDecl *[]>(NumDeclsFound); + std::copy(Decls.begin(), Decls.end(), DeclsFound.get()); } CXXBasePaths::decl_range CXXBasePaths::found_decls() { if (NumDeclsFound == 0) ComputeDeclsFound(); - return decl_range(decl_iterator(DeclsFound), - decl_iterator(DeclsFound + NumDeclsFound)); + return decl_range(decl_iterator(DeclsFound.get()), + decl_iterator(DeclsFound.get() + NumDeclsFound)); } /// isAmbiguous - Determines whether the set of paths provided is @@ -85,9 +85,14 @@ bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base, return false; Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); - return lookupInBases(&FindBaseClass, - const_cast<CXXRecordDecl*>(Base->getCanonicalDecl()), - Paths); + + const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); + // FIXME: Capturing 'this' is a workaround for name lookup bugs in GCC 4.7. + return lookupInBases( + [this, BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + return FindBaseClass(Specifier, Path, BaseDecl); + }, + Paths); } bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const { @@ -102,20 +107,20 @@ bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const { Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); - const void *BasePtr = static_cast<const void*>(Base->getCanonicalDecl()); - return lookupInBases(&FindVirtualBaseClass, - const_cast<void *>(BasePtr), - Paths); -} - -static bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget) { - // OpaqueTarget is a CXXRecordDecl*. - return Base->getCanonicalDecl() != (const CXXRecordDecl*) OpaqueTarget; + const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); + // FIXME: Capturing 'this' is a workaround for name lookup bugs in GCC 4.7. + return lookupInBases( + [this, BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + return FindVirtualBaseClass(Specifier, Path, BaseDecl); + }, + Paths); } bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const { - return forallBases(BaseIsNot, - const_cast<CXXRecordDecl *>(Base->getCanonicalDecl())); + const CXXRecordDecl *TargetDecl = Base->getCanonicalDecl(); + return forallBases([TargetDecl](const CXXRecordDecl *Base) { + return Base->getCanonicalDecl() != TargetDecl; + }); } bool @@ -129,8 +134,7 @@ CXXRecordDecl::isCurrentInstantiation(const DeclContext *CurContext) const { return false; } -bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, - void *OpaqueData, +bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches, bool AllowShortCircuit) const { SmallVector<const CXXRecordDecl*, 8> Queue; @@ -156,7 +160,7 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, } Queue.push_back(Base); - if (!BaseMatches(Base, OpaqueData)) { + if (!BaseMatches(Base)) { if (AllowShortCircuit) return false; AllMatches = false; continue; @@ -171,10 +175,9 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, return AllMatches; } -bool CXXBasePaths::lookupInBases(ASTContext &Context, - const CXXRecordDecl *Record, - CXXRecordDecl::BaseMatchesCallback *BaseMatches, - void *UserData) { +bool CXXBasePaths::lookupInBases( + ASTContext &Context, const CXXRecordDecl *Record, + CXXRecordDecl::BaseMatchesCallback BaseMatches) { bool FoundPath = false; // The access of the path down to this record. @@ -248,7 +251,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, // Track whether there's a path involving this specific base. bool FoundPathThroughBase = false; - if (BaseMatches(&BaseSpec, ScratchPath, UserData)) { + if (BaseMatches(&BaseSpec, ScratchPath)) { // We've found a path that terminates at this base. FoundPath = FoundPathThroughBase = true; if (isRecordingPaths()) { @@ -263,7 +266,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseSpec.getType()->castAs<RecordType>() ->getDecl()); - if (lookupInBases(Context, BaseRecord, BaseMatches, UserData)) { + if (lookupInBases(Context, BaseRecord, BaseMatches)) { // C++ [class.member.lookup]p2: // A member name f in one sub-object B hides a member name f in // a sub-object A if A is a base class sub-object of B. Any @@ -296,11 +299,10 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, return FoundPath; } -bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, - void *UserData, +bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths) const { // If we didn't find anything, report that. - if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, UserData)) + if (!Paths.lookupInBases(getASTContext(), this, BaseMatches)) return false; // If we're not recording paths or we won't ever find ambiguities, @@ -353,8 +355,8 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *BaseRecord) { - assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord && + const CXXRecordDecl *BaseRecord) { + assert(BaseRecord->getCanonicalDecl() == BaseRecord && "User data for FindBaseClass is not canonical!"); return Specifier->getType()->castAs<RecordType>()->getDecl() ->getCanonicalDecl() == BaseRecord; @@ -362,8 +364,8 @@ bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier, bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *BaseRecord) { - assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord && + const CXXRecordDecl *BaseRecord) { + assert(BaseRecord->getCanonicalDecl() == BaseRecord && "User data for FindBaseClass is not canonical!"); return Specifier->isVirtual() && Specifier->getType()->castAs<RecordType>()->getDecl() @@ -372,12 +374,11 @@ bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *Name) { + DeclarationName Name) { RecordDecl *BaseRecord = Specifier->getType()->castAs<RecordType>()->getDecl(); - DeclarationName N = DeclarationName::getFromOpaquePtr(Name); - for (Path.Decls = BaseRecord->lookup(N); + for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); Path.Decls = Path.Decls.slice(1)) { if (Path.Decls.front()->isInIdentifierNamespace(IDNS_Tag)) @@ -389,13 +390,12 @@ bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *Name) { + DeclarationName Name) { RecordDecl *BaseRecord = Specifier->getType()->castAs<RecordType>()->getDecl(); const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member; - DeclarationName N = DeclarationName::getFromOpaquePtr(Name); - for (Path.Decls = BaseRecord->lookup(N); + for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); Path.Decls = Path.Decls.slice(1)) { if (Path.Decls.front()->isInIdentifierNamespace(IDNS)) @@ -408,12 +408,11 @@ bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, bool CXXRecordDecl:: FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *Name) { + DeclarationName Name) { RecordDecl *BaseRecord = Specifier->getType()->castAs<RecordType>()->getDecl(); - DeclarationName N = DeclarationName::getFromOpaquePtr(Name); - for (Path.Decls = BaseRecord->lookup(N); + for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); Path.Decls = Path.Decls.slice(1)) { // FIXME: Refactor the "is it a nested-name-specifier?" check diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index ea4b2f5..427ca5e 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -207,13 +207,13 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D, // If we're ultimately computing the visibility of a type, look for // a 'type_visibility' attribute before looking for 'visibility'. if (kind == NamedDecl::VisibilityForType) { - if (const TypeVisibilityAttr *A = D->getAttr<TypeVisibilityAttr>()) { + if (const auto *A = D->getAttr<TypeVisibilityAttr>()) { return getVisibilityFromAttr(A); } } // If this declaration has an explicit visibility attribute, use it. - if (const VisibilityAttr *A = D->getAttr<VisibilityAttr>()) { + if (const auto *A = D->getAttr<VisibilityAttr>()) { return getVisibilityFromAttr(A); } @@ -252,8 +252,7 @@ getLVForTemplateParameterList(const TemplateParameterList *Params, // template <enum X> class A { ... }; // We have to be careful here, though, because we can be dealing with // dependent types. - if (const NonTypeTemplateParmDecl *NTTP = - dyn_cast<NonTypeTemplateParmDecl>(P)) { + if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) { // Handle the non-pack case first. if (!NTTP->isExpandedParameterPack()) { if (!NTTP->getType()->isDependentType()) { @@ -273,7 +272,7 @@ getLVForTemplateParameterList(const TemplateParameterList *Params, // Template template parameters can be restricted by their // template parameters, recursively. - const TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(P); + const auto *TTP = cast<TemplateTemplateParmDecl>(P); // Handle the non-pack case first. if (!TTP->isExpandedParameterPack()) { @@ -329,7 +328,7 @@ static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, continue; case TemplateArgument::Declaration: - if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) { + if (const auto *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) { assert(!usesTypeVisibility(ND)); LV.merge(getLVForDecl(ND, computation)); } @@ -541,7 +540,7 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) { if (!Opts.CPlusPlus || !Opts.InlineVisibilityHidden) return false; - const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + const auto *FD = dyn_cast<FunctionDecl>(D); if (!FD) return false; @@ -569,7 +568,7 @@ template <typename T> static bool isFirstInExternCContext(T *D) { } static bool isSingleLineLanguageLinkage(const Decl &D) { - if (const LinkageSpecDecl *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext())) + if (const auto *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext())) if (!SD->hasBraces()) return true; return false; @@ -587,7 +586,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // - an object, reference, function or function template that is // explicitly declared static; or, // (This bullet corresponds to C99 6.2.2p3.) - if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (const auto *Var = dyn_cast<VarDecl>(D)) { // Explicitly declared static. if (Var->getStorageClass() == SC_Static) return LinkageInfo::internal(); @@ -634,8 +633,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!"); if (D->isInAnonymousNamespace()) { - const VarDecl *Var = dyn_cast<VarDecl>(D); - const FunctionDecl *Func = dyn_cast<FunctionDecl>(D); + const auto *Var = dyn_cast<VarDecl>(D); + const auto *Func = dyn_cast<FunctionDecl>(D); + // FIXME: In C++11 onwards, anonymous namespaces should give decls + // within them internal linkage, not unique external linkage. if ((!Var || !isFirstInExternCContext(Var)) && (!Func || !isFirstInExternCContext(Func))) return LinkageInfo::uniqueExternal(); @@ -658,7 +659,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, for (const DeclContext *DC = D->getDeclContext(); !isa<TranslationUnitDecl>(DC); DC = DC->getParent()) { - const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC); + const auto *ND = dyn_cast<NamespaceDecl>(DC); if (!ND) continue; if (Optional<Visibility> Vis = getExplicitVisibility(ND, computation)) { LV.mergeVisibility(*Vis, true); @@ -692,7 +693,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // name of // // - an object or reference, unless it has internal linkage; or - if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (const auto *Var = dyn_cast<VarDecl>(D)) { // GCC applies the following optimization to variables and static // data members, but not to functions: // @@ -732,13 +733,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // 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)) { + if (const auto *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)) { + } else if (const auto *Function = dyn_cast<FunctionDecl>(D)) { // In theory, we can modify the function's LV by the LV of its // type unless it has C linkage (see comment above about variables // for justification). In practice, GCC doesn't do this, so it's @@ -785,7 +785,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // - a named enumeration (7.2), or an unnamed enumeration // defined in a typedef declaration in which the enumeration // has the typedef name for linkage purposes (7.1.3); or - } else if (const TagDecl *Tag = dyn_cast<TagDecl>(D)) { + } else if (const auto *Tag = dyn_cast<TagDecl>(D)) { // Unnamed tags have no linkage. if (!Tag->hasNameForLinkage()) return LinkageInfo::none(); @@ -793,8 +793,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // If this is a class template specialization, consider the // linkage of the template and template arguments. We're at file // scope, so we do not need to worry about nested specializations. - if (const ClassTemplateSpecializationDecl *spec - = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) { + if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) { mergeTemplateLV(LV, spec, computation); } @@ -808,7 +807,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // - a template, unless it is a function template that has // internal linkage (Clause 14); - } else if (const TemplateDecl *temp = dyn_cast<TemplateDecl>(D)) { + } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) { bool considerVisibility = !hasExplicitVisibilityAlready(computation); LinkageInfo tempLV = getLVForTemplateParameterList(temp->getTemplateParameters(), computation); @@ -824,10 +823,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, } else if (isa<ObjCInterfaceDecl>(D)) { // fallout + } else if (auto *TD = dyn_cast<TypedefNameDecl>(D)) { + // A typedef declaration has linkage if it gives a type a name for + // linkage purposes. + if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/true)) + return LinkageInfo::none(); + // Everything not covered here has no linkage. } else { - // FIXME: A typedef declaration has linkage if it gives a type a name for - // linkage purposes. return LinkageInfo::none(); } @@ -897,7 +900,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // Specifically, if this decl exists and has an explicit attribute. const NamedDecl *explicitSpecSuppressor = nullptr; - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { // If the type of the function uses a type with unique-external // linkage, it's not legally usable from outside this translation unit. // But only look at the type-as-written. If this function has an @@ -928,9 +931,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, explicitSpecSuppressor = MD; } - } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - if (const ClassTemplateSpecializationDecl *spec - = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { + } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { + if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { mergeTemplateLV(LV, spec, computation); if (spec->isExplicitSpecialization()) { explicitSpecSuppressor = spec; @@ -945,9 +947,8 @@ 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)) + } else if (const auto *VD = dyn_cast<VarDecl>(D)) { + if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(VD)) mergeTemplateLV(LV, spec, computation); // Modify the variable's linkage by its type, but ignore the @@ -962,7 +963,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, } // Template members. - } else if (const TemplateDecl *temp = dyn_cast<TemplateDecl>(D)) { + } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) { bool considerVisibility = (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit() && @@ -971,8 +972,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, getLVForTemplateParameterList(temp->getTemplateParameters(), computation); LV.mergeMaybeWithVisibility(tempLV, considerVisibility); - if (const RedeclarableTemplateDecl *redeclTemp = - dyn_cast<RedeclarableTemplateDecl>(temp)) { + if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) { if (isExplicitMemberSpecialization(redeclTemp)) { explicitSpecSuppressor = temp->getTemplatedDecl(); } @@ -1048,7 +1048,7 @@ getExplicitVisibilityAux(const NamedDecl *ND, // If this is a member class of a specialization of a class template // and the corresponding decl has explicit visibility, use that. - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND)) { + if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) { CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass(); if (InstantiatedFrom) return getVisibilityOf(InstantiatedFrom, kind); @@ -1057,8 +1057,7 @@ getExplicitVisibilityAux(const NamedDecl *ND, // If there wasn't explicit visibility there, and this is a // specialization of a class template, check for visibility // on the pattern. - if (const ClassTemplateSpecializationDecl *spec - = dyn_cast<ClassTemplateSpecializationDecl>(ND)) + if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(), kind); @@ -1069,7 +1068,7 @@ getExplicitVisibilityAux(const NamedDecl *ND, return getExplicitVisibilityAux(MostRecent, kind, true); } - if (const VarDecl *Var = dyn_cast<VarDecl>(ND)) { + if (const auto *Var = dyn_cast<VarDecl>(ND)) { if (Var->isStaticDataMember()) { VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember(); if (InstantiatedFrom) @@ -1083,7 +1082,7 @@ getExplicitVisibilityAux(const NamedDecl *ND, return None; } // Also handle function template specializations. - if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(ND)) { + if (const auto *fn = dyn_cast<FunctionDecl>(ND)) { // If the function is a specialization of a template with an // explicit visibility attribute, use that. if (FunctionTemplateSpecializationInfo *templateInfo @@ -1101,7 +1100,7 @@ getExplicitVisibilityAux(const NamedDecl *ND, } // The visibility of a template is stored in the templated decl. - if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(ND)) + if (const auto *TD = dyn_cast<TemplateDecl>(ND)) return getVisibilityOf(TD->getTemplatedDecl(), kind); return None; @@ -1122,7 +1121,7 @@ static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, return getLVForDecl(cast<NamedDecl>(ContextDecl), computation); } - if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) + if (const auto *ND = dyn_cast<NamedDecl>(DC)) return getLVForDecl(ND, computation); return LinkageInfo::external(); @@ -1130,7 +1129,7 @@ static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, static LinkageInfo getLVForLocalDecl(const NamedDecl *D, LVComputationKind computation) { - if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { + if (const auto *Function = dyn_cast<FunctionDecl>(D)) { if (Function->isInAnonymousNamespace() && !Function->isInExternCContext()) return LinkageInfo::uniqueExternal(); @@ -1153,7 +1152,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, return LV; } - if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (const auto *Var = dyn_cast<VarDecl>(D)) { if (Var->hasExternalStorage()) { if (Var->isInAnonymousNamespace() && !Var->isInExternCContext()) return LinkageInfo::uniqueExternal(); @@ -1185,18 +1184,18 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D, return LinkageInfo::none(); const Decl *OuterD = getOutermostFuncOrBlockContext(D); - if (!OuterD) + if (!OuterD || OuterD->isInvalidDecl()) return LinkageInfo::none(); LinkageInfo LV; - if (const BlockDecl *BD = dyn_cast<BlockDecl>(OuterD)) { + if (const auto *BD = dyn_cast<BlockDecl>(OuterD)) { if (!BD->getBlockManglingNumber()) return LinkageInfo::none(); LV = getLVForClosure(BD->getDeclContext()->getRedeclContext(), BD->getBlockManglingContextDecl(), computation); } else { - const FunctionDecl *FD = cast<FunctionDecl>(OuterD); + const auto *FD = cast<FunctionDecl>(OuterD); if (!FD->isInlined() && !isTemplateInstantiation(FD->getTemplateSpecializationKind())) return LinkageInfo::none(); @@ -1224,13 +1223,45 @@ getOutermostEnclosingLambda(const CXXRecordDecl *Record) { static LinkageInfo computeLVForDecl(const NamedDecl *D, LVComputationKind computation) { + // Internal_linkage attribute overrides other considerations. + if (D->hasAttr<InternalLinkageAttr>()) + return LinkageInfo::internal(); + // Objective-C: treat all Objective-C declarations as having external // linkage. switch (D->getKind()) { default: break; + + // Per C++ [basic.link]p2, only the names of objects, references, + // functions, types, templates, namespaces, and values ever have linkage. + // + // Note that the name of a typedef, namespace alias, using declaration, + // and so on are not the name of the corresponding type, namespace, or + // declaration, so they do *not* have linkage. + case Decl::ImplicitParam: + case Decl::Label: + case Decl::NamespaceAlias: case Decl::ParmVar: + case Decl::Using: + case Decl::UsingShadow: + case Decl::UsingDirective: return LinkageInfo::none(); + + case Decl::EnumConstant: + // C++ [basic.link]p4: an enumerator has the linkage of its enumeration. + return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation); + + case Decl::Typedef: + case Decl::TypeAlias: + // A typedef declaration has linkage if it gives a type a name for + // linkage purposes. + if (!D->getASTContext().getLangOpts().CPlusPlus || + !cast<TypedefNameDecl>(D) + ->getAnonDeclWithTypedefName(/*AnyRedecl*/true)) + return LinkageInfo::none(); + break; + case Decl::TemplateTemplateParm: // count these as external case Decl::NonTypeTemplateParm: case Decl::ObjCAtDefsField: @@ -1245,7 +1276,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, return LinkageInfo::external(); case Decl::CXXRecord: { - const CXXRecordDecl *Record = cast<CXXRecordDecl>(D); + const auto *Record = cast<CXXRecordDecl>(D); if (Record->isLambda()) { if (!Record->getLambdaManglingNumber()) { // This lambda has no mangling number, so it's internal. @@ -1314,6 +1345,10 @@ class LinkageComputer { public: static LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation) { + // Internal_linkage attribute overrides other considerations. + if (D->hasAttr<InternalLinkageAttr>()) + return LinkageInfo::internal(); + if (computation == LVForLinkageOnly && D->hasCachedLinkage()) return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); @@ -1336,7 +1371,7 @@ public: // computed also does. NamedDecl *Old = nullptr; for (auto I : D->redecls()) { - NamedDecl *T = cast<NamedDecl>(I); + auto *T = cast<NamedDecl>(I); if (T == D) continue; if (!T->isInvalidDecl() && T->hasCachedLinkage()) { @@ -1388,28 +1423,29 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, for (ContextsTy::reverse_iterator I = Contexts.rbegin(), E = Contexts.rend(); I != E; ++I) { - if (const ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(*I)) { + if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(*I)) { OS << Spec->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); TemplateSpecializationType::PrintTemplateArgumentList(OS, TemplateArgs.data(), TemplateArgs.size(), P); - } else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(*I)) { + } else if (const auto *ND = dyn_cast<NamespaceDecl>(*I)) { if (P.SuppressUnwrittenScope && (ND->isAnonymousNamespace() || ND->isInline())) continue; - if (ND->isAnonymousNamespace()) - OS << "(anonymous namespace)"; + if (ND->isAnonymousNamespace()) { + OS << (P.MSVCFormatting ? "`anonymous namespace\'" + : "(anonymous namespace)"); + } else OS << *ND; - } else if (const RecordDecl *RD = dyn_cast<RecordDecl>(*I)) { + } else if (const auto *RD = dyn_cast<RecordDecl>(*I)) { if (!RD->getIdentifier()) OS << "(anonymous " << RD->getKindName() << ')'; else OS << *RD; - } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { + } else if (const auto *FD = dyn_cast<FunctionDecl>(*I)) { const FunctionProtoType *FT = nullptr; if (FD->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>()); @@ -1430,6 +1466,15 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, } } OS << ')'; + } else if (const auto *ED = dyn_cast<EnumDecl>(*I)) { + // C++ [dcl.enum]p10: Each enum-name and each unscoped + // enumerator is declared in the scope that immediately contains + // the enum-specifier. Each scoped enumerator is declared in the + // scope of the enumeration. + if (ED->isScoped() || ED->getIdentifier()) + OS << *ED; + else + continue; } else { OS << *cast<NamedDecl>(*I); } @@ -1451,32 +1496,6 @@ void NamedDecl::getNameForDiagnostic(raw_ostream &OS, printName(OS); } -static bool isKindReplaceableBy(Decl::Kind OldK, Decl::Kind NewK) { - // For method declarations, we never replace. - if (ObjCMethodDecl::classofKind(NewK)) - return false; - - if (OldK == NewK) - return true; - - // A compatibility alias for a class can be replaced by an interface. - if (ObjCCompatibleAliasDecl::classofKind(OldK) && - ObjCInterfaceDecl::classofKind(NewK)) - return true; - - // A typedef-declaration, alias-declaration, or Objective-C class declaration - // can replace another declaration of the same type. Semantic analysis checks - // that we have matching types. - if ((TypedefNameDecl::classofKind(OldK) || - ObjCInterfaceDecl::classofKind(OldK)) && - (TypedefNameDecl::classofKind(NewK) || - ObjCInterfaceDecl::classofKind(NewK))) - return true; - - // Otherwise, a kind mismatch implies that the declaration is not replaced. - return false; -} - template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) { return true; } @@ -1500,9 +1519,19 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { if (OldD->isFromASTFile() && isFromASTFile()) return false; - if (!isKindReplaceableBy(OldD->getKind(), getKind())) + // A kind mismatch implies that the declaration is not replaced. + if (OldD->getKind() != getKind()) + return false; + + // For method declarations, we never replace. (Why?) + if (isa<ObjCMethodDecl>(this)) return false; + // For parameters, pick the newer one. This is either an error or (in + // Objective-C) permitted as an extension. + if (isa<ParmVarDecl>(this)) + return true; + // Inline namespaces can give us two declarations with the same // name and kind in the same scope but different contexts; we should // keep both declarations in this case. @@ -1510,28 +1539,8 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { OldD->getDeclContext()->getRedeclContext())) return false; - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) - // For function declarations, we keep track of redeclarations. - // FIXME: This returns false for functions that should in fact be replaced. - // Instead, perform some kind of type check? - if (FD->getPreviousDecl() != OldD) - return false; - - // For function templates, the underlying function declarations are linked. - if (const FunctionTemplateDecl *FunctionTemplate = - dyn_cast<FunctionTemplateDecl>(this)) - return FunctionTemplate->getTemplatedDecl()->declarationReplaces( - cast<FunctionTemplateDecl>(OldD)->getTemplatedDecl()); - - // Using shadow declarations can be overloaded on their target declarations - // if they introduce functions. - // FIXME: If our target replaces the old target, can we replace the old - // shadow declaration? - if (auto *USD = dyn_cast<UsingShadowDecl>(this)) - if (USD->getTargetDecl() != cast<UsingShadowDecl>(OldD)->getTargetDecl()) - return false; - - // Using declarations can be overloaded if they introduce functions. + // Using declarations can be replaced if they import the same name from the + // same context. if (auto *UD = dyn_cast<UsingDecl>(this)) { ASTContext &Context = getASTContext(); return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) == @@ -1546,13 +1555,20 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { } // UsingDirectiveDecl's are not really NamedDecl's, and all have same name. - // We want to keep it, unless it nominates same namespace. + // They can be replaced if they nominate the same namespace. + // FIXME: Is this true even if they have different module visibility? if (auto *UD = dyn_cast<UsingDirectiveDecl>(this)) return UD->getNominatedNamespace()->getOriginalNamespace() == cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace() ->getOriginalNamespace(); - if (!IsKnownNewer && isRedeclarable(getKind())) { + if (isRedeclarable(getKind())) { + if (getCanonicalDecl() != OldD->getCanonicalDecl()) + return false; + + if (IsKnownNewer) + return true; + // Check whether this is actually newer than OldD. We want to keep the // newer declaration. This loop will usually only iterate once, because // OldD is usually the previous declaration. @@ -1567,11 +1583,16 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { if (D->isCanonicalDecl()) return false; } + + // It's a newer declaration of the same kind of declaration in the same + // scope: we want this decl instead of the existing one. + return true; } - // It's a newer declaration of the same kind of declaration in the same scope, - // and not an overload: we want this decl instead of the existing one. - return true; + // In all other cases, we need to keep both declarations in case they have + // different visibility. Any attempt to use the name will result in an + // ambiguity if more than one is visible. + return false; } bool NamedDecl::hasLinkage() const { @@ -1580,12 +1601,15 @@ bool NamedDecl::hasLinkage() const { NamedDecl *NamedDecl::getUnderlyingDeclImpl() { NamedDecl *ND = this; - while (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND)) + while (auto *UD = dyn_cast<UsingShadowDecl>(ND)) ND = UD->getTargetDecl(); - if (ObjCCompatibleAliasDecl *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND)) + if (auto *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND)) return AD->getClassInterface(); + if (auto *AD = dyn_cast<NamespaceAliasDecl>(ND)) + return AD->getNamespace(); + return ND; } @@ -1599,8 +1623,7 @@ bool NamedDecl::isCXXInstanceMember() const { if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D)) return true; - if (const CXXMethodDecl *MD = - dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction())) + if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction())) return MD->isInstance(); return false; } @@ -1628,7 +1651,7 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { // Make sure the extended decl info is allocated. if (!hasExtInfo()) { // Save (non-extended) type source info pointer. - TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>(); + auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>(); // Allocate external info struct. DeclInfo = new (getASTContext()) ExtInfo; // Restore savedTInfo into (extended) decl info. @@ -1653,22 +1676,20 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { } } -void -DeclaratorDecl::setTemplateParameterListsInfo(ASTContext &Context, - unsigned NumTPLists, - TemplateParameterList **TPLists) { - assert(NumTPLists > 0); +void DeclaratorDecl::setTemplateParameterListsInfo( + ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) { + assert(!TPLists.empty()); // Make sure the extended decl info is allocated. if (!hasExtInfo()) { // Save (non-extended) type source info pointer. - TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>(); + auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>(); // Allocate external info struct. DeclInfo = new (getASTContext()) ExtInfo; // Restore savedTInfo into (extended) decl info. getExtInfo()->TInfo = savedTInfo; } // Set the template parameter lists info. - getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); + getExtInfo()->setTemplateParameterListsInfo(Context, TPLists); } SourceLocation DeclaratorDecl::getOuterLocStart() const { @@ -1726,13 +1747,8 @@ SourceRange DeclaratorDecl::getSourceRange() const { return SourceRange(getOuterLocStart(), RangeEnd); } -void -QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, - unsigned NumTPLists, - TemplateParameterList **TPLists) { - assert((NumTPLists == 0 || TPLists != nullptr) && - "Empty array of template parameters with positive size!"); - +void QualifierInfo::setTemplateParameterListsInfo( + ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) { // Free previous template parameters (if any). if (NumTemplParamLists > 0) { Context.Deallocate(TemplParamLists); @@ -1740,10 +1756,10 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, NumTemplParamLists = 0; } // Set info on matched template parameter lists (if any). - if (NumTPLists > 0) { - TemplParamLists = new (Context) TemplateParameterList*[NumTPLists]; - NumTemplParamLists = NumTPLists; - std::copy(TPLists, TPLists + NumTPLists, TemplParamLists); + if (!TPLists.empty()) { + TemplParamLists = new (Context) TemplateParameterList *[TPLists.size()]; + NumTemplParamLists = TPLists.size(); + std::copy(TPLists.begin(), TPLists.end(), TemplParamLists); } } @@ -1756,7 +1772,6 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { case SC_None: break; case SC_Auto: return "auto"; case SC_Extern: return "extern"; - case SC_OpenCLWorkGroupLocal: return "<<work-group-local>>"; case SC_PrivateExtern: return "__private_extern__"; case SC_Register: return "register"; case SC_Static: return "static"; @@ -1995,7 +2010,7 @@ VarDecl *VarDecl::getDefinition(ASTContext &C) { VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { DefinitionKind Kind = DeclarationOnly; - + const VarDecl *First = getFirstDecl(); for (auto I : First->redecls()) { Kind = std::max(Kind, I->isThisDeclarationADefinition(C)); @@ -2016,6 +2031,31 @@ const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const { return nullptr; } +bool VarDecl::hasInit() const { + if (auto *P = dyn_cast<ParmVarDecl>(this)) + if (P->hasUnparsedDefaultArg() || P->hasUninstantiatedDefaultArg()) + return false; + + return !Init.isNull(); +} + +Expr *VarDecl::getInit() { + if (!hasInit()) + return nullptr; + + if (auto *S = Init.dyn_cast<Stmt *>()) + return cast<Expr>(S); + + return cast_or_null<Expr>(Init.get<EvaluatedStmt *>()->Value); +} + +Stmt **VarDecl::getInitAddress() { + if (auto *ES = Init.dyn_cast<EvaluatedStmt *>()) + return &ES->Value; + + return Init.getAddrOfPtr1(); +} + bool VarDecl::isOutOfLine() const { if (Decl::isOutOfLine()) return true; @@ -2045,7 +2085,7 @@ VarDecl *VarDecl::getOutOfLineDefinition() { } void VarDecl::setInit(Expr *I) { - if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) { + if (auto *Eval = Init.dyn_cast<EvaluatedStmt *>()) { Eval->~EvaluatedStmt(); getASTContext().Deallocate(Eval); } @@ -2084,15 +2124,14 @@ bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const { /// form, which contains extra information on the evaluated value of the /// initializer. EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const { - EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); + auto *Eval = Init.dyn_cast<EvaluatedStmt *>(); if (!Eval) { - Stmt *S = Init.get<Stmt *>(); // Note: EvaluatedStmt contains an APValue, which usually holds // resources not allocated from the ASTContext. We need to do some // work to avoid leaking those, but we do so in VarDecl::evaluateValue // where we can detect whether there's anything to clean up or not. Eval = new (getASTContext()) EvaluatedStmt; - Eval->Value = S; + Eval->Value = Init.get<Stmt *>(); Init = Eval; } return Eval; @@ -2120,7 +2159,7 @@ APValue *VarDecl::evaluateValue( if (Eval->WasEvaluated) return Eval->Evaluated.isUninit() ? nullptr : &Eval->Evaluated; - const Expr *Init = cast<Expr>(Eval->Value); + const auto *Init = cast<Expr>(Eval->Value); assert(!Init->isValueDependent()); if (Eval->IsEvaluating) { @@ -2156,6 +2195,27 @@ APValue *VarDecl::evaluateValue( return Result ? &Eval->Evaluated : nullptr; } +APValue *VarDecl::getEvaluatedValue() const { + if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) + if (Eval->WasEvaluated) + return &Eval->Evaluated; + + return nullptr; +} + +bool VarDecl::isInitKnownICE() const { + if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) + return Eval->CheckedICE; + + return false; +} + +bool VarDecl::isInitICE() const { + assert(isInitKnownICE() && + "Check whether we already know that the initializer is an ICE"); + return Init.get<EvaluatedStmt *>()->IsICE; +} + bool VarDecl::checkInitIsICE() const { // Initializers of weak variables are never ICEs. if (isWeak()) @@ -2167,7 +2227,7 @@ bool VarDecl::checkInitIsICE() const { // integral constant expression. return Eval->IsICE; - const Expr *Init = cast<Expr>(Eval->Value); + const auto *Init = cast<Expr>(Eval->Value); assert(!Init->isValueDependent()); // In C++11, evaluate the initializer to check whether it's a constant @@ -2200,8 +2260,7 @@ VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { } TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const { - if (const VarTemplateSpecializationDecl *Spec = - dyn_cast<VarTemplateSpecializationDecl>(this)) + if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this)) return Spec->getSpecializationKind(); if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) @@ -2211,8 +2270,7 @@ TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const { } SourceLocation VarDecl::getPointOfInstantiation() const { - if (const VarTemplateSpecializationDecl *Spec = - dyn_cast<VarTemplateSpecializationDecl>(this)) + if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this)) return Spec->getPointOfInstantiation(); if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) @@ -2285,7 +2343,7 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, QualType ParmVarDecl::getOriginalType() const { TypeSourceInfo *TSI = getTypeSourceInfo(); QualType T = TSI ? TSI->getType() : getType(); - if (const DecayedType *DT = dyn_cast<DecayedType>(T)) + if (const auto *DT = dyn_cast<DecayedType>(T)) return DT->getOriginalType(); return T; } @@ -2315,22 +2373,56 @@ Expr *ParmVarDecl::getDefaultArg() { assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!"); assert(!hasUninstantiatedDefaultArg() && "Default argument is not yet instantiated!"); - + Expr *Arg = getInit(); - if (ExprWithCleanups *E = dyn_cast_or_null<ExprWithCleanups>(Arg)) + if (auto *E = dyn_cast_or_null<ExprWithCleanups>(Arg)) return E->getSubExpr(); return Arg; } +void ParmVarDecl::setDefaultArg(Expr *defarg) { + ParmVarDeclBits.DefaultArgKind = DAK_Normal; + Init = defarg; +} + SourceRange ParmVarDecl::getDefaultArgRange() const { - if (const Expr *E = getInit()) - return E->getSourceRange(); + switch (ParmVarDeclBits.DefaultArgKind) { + case DAK_None: + case DAK_Unparsed: + // Nothing we can do here. + return SourceRange(); - if (hasUninstantiatedDefaultArg()) + case DAK_Uninstantiated: return getUninstantiatedDefaultArg()->getSourceRange(); - return SourceRange(); + case DAK_Normal: + if (const Expr *E = getInit()) + return E->getSourceRange(); + + // Missing an actual expression, may be invalid. + return SourceRange(); + } + llvm_unreachable("Invalid default argument kind."); +} + +void ParmVarDecl::setUninstantiatedDefaultArg(Expr *arg) { + ParmVarDeclBits.DefaultArgKind = DAK_Uninstantiated; + Init = arg; +} + +Expr *ParmVarDecl::getUninstantiatedDefaultArg() { + assert(hasUninstantiatedDefaultArg() && + "Wrong kind of initialization expression!"); + return cast_or_null<Expr>(Init.get<Stmt *>()); +} + +bool ParmVarDecl::hasDefaultArg() const { + // FIXME: We should just return false for DAK_None here once callers are + // prepared for the case that we encountered an invalid default argument and + // were unable to even build an invalid expression. + return hasUnparsedDefaultArg() || hasUninstantiatedDefaultArg() || + !Init.isNull(); } bool ParmVarDecl::isParameterPack() const { @@ -2360,7 +2452,7 @@ void FunctionDecl::getNameForDiagnostic( } bool FunctionDecl::isVariadic() const { - if (const FunctionProtoType *FT = getType()->getAs<FunctionProtoType>()) + if (const auto *FT = getType()->getAs<FunctionProtoType>()) return FT->isVariadic(); return false; } @@ -2421,7 +2513,7 @@ void FunctionDecl::setBody(Stmt *B) { void FunctionDecl::setPure(bool P) { IsPure = P; if (P) - if (CXXRecordDecl *Parent = dyn_cast<CXXRecordDecl>(getDeclContext())) + if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext())) Parent->markedVirtualFunctionPure(); } @@ -2476,7 +2568,7 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) return false; - const FunctionProtoType *proto = getType()->castAs<FunctionProtoType>(); + const auto *proto = getType()->castAs<FunctionProtoType>(); if (proto->getNumParams() != 2 || proto->isVariadic()) return false; @@ -2505,7 +2597,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) return false; - const FunctionProtoType *FPT = getType()->castAs<FunctionProtoType>(); + const auto *FPT = getType()->castAs<FunctionProtoType>(); if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic()) return false; @@ -2547,7 +2639,7 @@ bool FunctionDecl::isInExternCXXContext() const { } bool FunctionDecl::isGlobal() const { - if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this)) + if (const auto *Method = dyn_cast<CXXMethodDecl>(this)) return Method->isStatic(); if (getCanonicalDecl()->getStorageClass() == SC_Static) @@ -2556,7 +2648,7 @@ bool FunctionDecl::isGlobal() const { for (const DeclContext *DC = getDeclContext(); DC->isNamespace(); DC = DC->getParent()) { - if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) { + if (const auto *Namespace = cast<NamespaceDecl>(DC)) { if (!Namespace->getDeclName()) return false; break; @@ -2608,8 +2700,8 @@ unsigned FunctionDecl::getBuiltinID() const { ASTContext &Context = getASTContext(); if (Context.getLangOpts().CPlusPlus) { - const LinkageSpecDecl *LinkageDecl = dyn_cast<LinkageSpecDecl>( - getFirstDecl()->getDeclContext()); + const auto *LinkageDecl = + dyn_cast<LinkageSpecDecl>(getFirstDecl()->getDeclContext()); // In C++, the first declaration of a builtin is always inside an implicit // extern "C". // FIXME: A recognised library function may not be directly in an extern "C" @@ -2649,7 +2741,7 @@ 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 FunctionProtoType *FPT = getType()->getAs<FunctionProtoType>(); + const auto *FPT = getType()->getAs<FunctionProtoType>(); return FPT ? FPT->getNumParams() : 0; } @@ -2711,7 +2803,8 @@ bool FunctionDecl::isMSExternInline() const { assert(isInlined() && "expected to get called on an inlined function!"); const ASTContext &Context = getASTContext(); - if (!Context.getLangOpts().MSVCCompat && !hasAttr<DLLExportAttr>()) + if (!Context.getTargetInfo().getCXXABI().isMicrosoft() && + !hasAttr<DLLExportAttr>()) return false; for (const FunctionDecl *FD = getMostRecentDecl(); FD; @@ -2840,7 +2933,7 @@ bool FunctionDecl::hasUnusedResultAttr() const { QualType RetType = getReturnType(); if (RetType->isRecordType()) { const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl(); - const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(this); + const auto *MD = dyn_cast<CXXMethodDecl>(this); if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() && !(MD && MD->getCorrespondingMethodInClass(Ret, true))) return true; @@ -2952,6 +3045,10 @@ FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { return nullptr; } +MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const { + return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>(); +} + void FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD, @@ -2963,6 +3060,14 @@ FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C, TemplateOrSpecialization = Info; } +FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const { + return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl *>(); +} + +void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) { + TemplateOrSpecialization = Template; +} + bool FunctionDecl::isImplicitlyInstantiable() const { // If the function is invalid, it can't be implicitly instantiated. if (isInvalidDecl()) @@ -3069,6 +3174,12 @@ FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const { return getASTContext().getClassScopeSpecializationPattern(this); } +FunctionTemplateSpecializationInfo * +FunctionDecl::getTemplateSpecializationInfo() const { + return TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>(); +} + const TemplateArgumentList * FunctionDecl::getTemplateSpecializationArgs() const { if (FunctionTemplateSpecializationInfo *Info @@ -3115,33 +3226,41 @@ FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context, const UnresolvedSetImpl &Templates, const TemplateArgumentListInfo &TemplateArgs) { assert(TemplateOrSpecialization.isNull()); - size_t Size = sizeof(DependentFunctionTemplateSpecializationInfo); - Size += Templates.size() * sizeof(FunctionTemplateDecl*); - Size += TemplateArgs.size() * sizeof(TemplateArgumentLoc); - void *Buffer = Context.Allocate(Size); DependentFunctionTemplateSpecializationInfo *Info = - new (Buffer) DependentFunctionTemplateSpecializationInfo(Templates, - TemplateArgs); + DependentFunctionTemplateSpecializationInfo::Create(Context, Templates, + TemplateArgs); TemplateOrSpecialization = Info; } +DependentFunctionTemplateSpecializationInfo * +FunctionDecl::getDependentSpecializationInfo() const { + return TemplateOrSpecialization + .dyn_cast<DependentFunctionTemplateSpecializationInfo *>(); +} + +DependentFunctionTemplateSpecializationInfo * +DependentFunctionTemplateSpecializationInfo::Create( + ASTContext &Context, const UnresolvedSetImpl &Ts, + const TemplateArgumentListInfo &TArgs) { + void *Buffer = Context.Allocate( + totalSizeToAlloc<TemplateArgumentLoc, FunctionTemplateDecl *>( + TArgs.size(), Ts.size())); + return new (Buffer) DependentFunctionTemplateSpecializationInfo(Ts, TArgs); +} + DependentFunctionTemplateSpecializationInfo:: DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts, const TemplateArgumentListInfo &TArgs) : AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) { - static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0, - "Trailing data is unaligned!"); - d.NumTemplates = Ts.size(); - d.NumArgs = TArgs.size(); + NumTemplates = Ts.size(); + NumArgs = TArgs.size(); - FunctionTemplateDecl **TsArray = - const_cast<FunctionTemplateDecl**>(getTemplates()); + FunctionTemplateDecl **TsArray = getTrailingObjects<FunctionTemplateDecl *>(); for (unsigned I = 0, E = Ts.size(); I != E; ++I) TsArray[I] = cast<FunctionTemplateDecl>(Ts[I]->getUnderlyingDecl()); - TemplateArgumentLoc *ArgsArray = - const_cast<TemplateArgumentLoc*>(getTemplateArgs()); + TemplateArgumentLoc *ArgsArray = getTrailingObjects<TemplateArgumentLoc>(); for (unsigned I = 0, E = TArgs.size(); I != E; ++I) new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]); } @@ -3335,7 +3454,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const { if (!isImplicit() || getDeclName()) return false; - if (const RecordType *Record = getType()->getAs<RecordType>()) + if (const auto *Record = getType()->getAs<RecordType>()) return Record->getDecl()->isAnonymousStructOrUnion(); return false; @@ -3343,7 +3462,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const { unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { assert(isBitField() && "not a bitfield"); - Expr *BitWidth = static_cast<Expr *>(InitStorage.getPointer()); + auto *BitWidth = static_cast<Expr *>(InitStorage.getPointer()); return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue(); } @@ -3372,7 +3491,7 @@ SourceRange FieldDecl::getSourceRange() const { case ISK_BitWidthOrNothing: case ISK_InClassCopyInit: case ISK_InClassListInit: - if (const Expr *E = static_cast<const Expr *>(InitStorage.getPointer())) + if (const auto *E = static_cast<const Expr *>(InitStorage.getPointer())) return SourceRange(getInnerLocStart(), E->getLocEnd()); // FALLTHROUGH @@ -3408,7 +3527,7 @@ SourceRange TagDecl::getSourceRange() const { TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); } void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { - NamedDeclOrQualifier = TDD; + TypedefNameDeclOrQualifier = TDD; if (const Type *T = getTypeForDecl()) { (void)T; assert(T->isLinkageValid()); @@ -3419,7 +3538,7 @@ void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { void TagDecl::startDefinition() { IsBeingDefined = true; - if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(this)) { + if (auto *D = dyn_cast<CXXRecordDecl>(this)) { struct CXXRecordDecl::DefinitionData *Data = new (getASTContext()) struct CXXRecordDecl::DefinitionData(D); for (auto I : redecls()) @@ -3452,7 +3571,7 @@ TagDecl *TagDecl::getDefinition() const { } } - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this)) + if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(this)) return CXXRD->getDefinition(); for (auto R : redecls()) @@ -3466,7 +3585,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (QualifierLoc) { // Make sure the extended qualifier info is allocated. if (!hasExtInfo()) - NamedDeclOrQualifier = new (getASTContext()) ExtInfo; + TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; // Set qualifier info. getExtInfo()->QualifierLoc = QualifierLoc; } else { @@ -3474,7 +3593,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { getASTContext().Deallocate(getExtInfo()); - NamedDeclOrQualifier = (TypedefNameDecl*)nullptr; + TypedefNameDeclOrQualifier = (TypedefNameDecl *)nullptr; } else getExtInfo()->QualifierLoc = QualifierLoc; @@ -3482,16 +3601,15 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { } } -void TagDecl::setTemplateParameterListsInfo(ASTContext &Context, - unsigned NumTPLists, - TemplateParameterList **TPLists) { - assert(NumTPLists > 0); +void TagDecl::setTemplateParameterListsInfo( + ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) { + assert(!TPLists.empty()); // Make sure the extended decl info is allocated. if (!hasExtInfo()) // Allocate external info struct. - NamedDeclOrQualifier = new (getASTContext()) ExtInfo; + TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; // Set the template parameter lists info. - getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); + getExtInfo()->setTemplateParameterListsInfo(Context, TPLists); } //===----------------------------------------------------------------------===// @@ -3505,9 +3623,8 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed) { - EnumDecl *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl, - IsScoped, IsScopedUsingClassTag, - IsFixed); + auto *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; @@ -3647,10 +3764,6 @@ bool RecordDecl::isMsStruct(const ASTContext &C) const { return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1; } -static bool isFieldOrIndirectField(Decl::Kind K) { - return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K); -} - void RecordDecl::LoadFieldsFromExternalStorage() const { ExternalASTSource *Source = getASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); @@ -3659,16 +3772,10 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { ExternalASTSource::Deserializing TheFields(Source); SmallVector<Decl*, 64> Decls; - LoadedFieldsFromExternalStorage = true; - switch (Source->FindExternalLexicalDecls(this, isFieldOrIndirectField, - Decls)) { - case ELR_Success: - break; - - case ELR_AlreadyLoaded: - case ELR_Failure: - return; - } + LoadedFieldsFromExternalStorage = true; + Source->FindExternalLexicalDecls(this, [](Decl::Kind K) { + return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K); + }, Decls); #ifndef NDEBUG // Check that all decls we got were FieldDecls. @@ -3690,7 +3797,7 @@ bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { !Context.getLangOpts().SanitizeAddressFieldPadding) return false; const auto &Blacklist = Context.getSanitizerBlacklist(); - const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this); + const auto *CXXRD = dyn_cast<CXXRecordDecl>(this); // We may be able to relax some of these requirements. int ReasonToReject = -1; if (!CXXRD || CXXRD->isExternCContext()) @@ -3731,9 +3838,9 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const { if (I->getIdentifier()) return I; - if (const RecordType *RT = I->getType()->getAs<RecordType>()) + if (const auto *RT = I->getType()->getAs<RecordType>()) if (const FieldDecl *NamedDataMember = - RT->getDecl()->findFirstNamedDataMember()) + RT->getDecl()->findFirstNamedDataMember()) return NamedDataMember; } @@ -3757,26 +3864,17 @@ void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { } } -void BlockDecl::setCaptures(ASTContext &Context, - const Capture *begin, - const Capture *end, - bool capturesCXXThis) { - CapturesCXXThis = capturesCXXThis; +void BlockDecl::setCaptures(ASTContext &Context, ArrayRef<Capture> Captures, + bool CapturesCXXThis) { + this->CapturesCXXThis = CapturesCXXThis; + this->NumCaptures = Captures.size(); - if (begin == end) { - NumCaptures = 0; - Captures = nullptr; + if (Captures.empty()) { + this->Captures = nullptr; return; } - NumCaptures = end - begin; - - // Avoid new Capture[] because we don't want to provide a default - // constructor. - size_t allocationSize = NumCaptures * sizeof(Capture); - void *buffer = Context.Allocate(allocationSize, /*alignment*/sizeof(void*)); - memcpy(buffer, begin, allocationSize); - Captures = static_cast<Capture*>(buffer); + this->Captures = Captures.copy(Context).data(); } bool BlockDecl::capturesVariable(const VarDecl *variable) const { @@ -3889,18 +3987,28 @@ BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) BlockDecl(nullptr, SourceLocation()); } +CapturedDecl::CapturedDecl(DeclContext *DC, unsigned NumParams) + : Decl(Captured, DC, SourceLocation()), DeclContext(Captured), + NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) {} + CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC, unsigned NumParams) { - return new (C, DC, NumParams * sizeof(ImplicitParamDecl *)) + return new (C, DC, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams)) CapturedDecl(DC, NumParams); } CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumParams) { - return new (C, ID, NumParams * sizeof(ImplicitParamDecl *)) + return new (C, ID, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams)) CapturedDecl(nullptr, NumParams); } +Stmt *CapturedDecl::getBody() const { return BodyAndNothrow.getPointer(); } +void CapturedDecl::setBody(Stmt *B) { BodyAndNothrow.setPointer(B); } + +bool CapturedDecl::isNothrow() const { return BodyAndNothrow.getInt(); } +void CapturedDecl::setNothrow(bool Nothrow) { BodyAndNothrow.setInt(Nothrow); } + EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, SourceLocation L, IdentifierInfo *Id, QualType T, @@ -3916,16 +4024,26 @@ EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void IndirectFieldDecl::anchor() { } +IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName N, + QualType T, NamedDecl **CH, unsigned CHS) + : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) { + // In C++, indirect field declarations conflict with tag declarations in the + // same scope, so add them to IDNS_Tag so that tag redeclaration finds them. + if (C.getLangOpts().CPlusPlus) + IdentifierNamespace |= IDNS_Tag; +} + IndirectFieldDecl * IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, NamedDecl **CH, unsigned CHS) { - return new (C, DC) IndirectFieldDecl(DC, L, Id, T, CH, CHS); + return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH, CHS); } IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(), + return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(), DeclarationName(), QualType(), nullptr, 0); } @@ -4042,9 +4160,9 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, NextLocalImport() { assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size()); - SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(this + 1); - memcpy(StoredLocs, IdentifierLocs.data(), - IdentifierLocs.size() * sizeof(SourceLocation)); + auto *StoredLocs = getTrailingObjects<SourceLocation>(); + std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(), + StoredLocs); } ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, @@ -4052,13 +4170,14 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, false), NextLocalImport() { - *reinterpret_cast<SourceLocation *>(this + 1) = EndLoc; + *getTrailingObjects<SourceLocation>() = EndLoc; } ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, Module *Imported, ArrayRef<SourceLocation> IdentifierLocs) { - return new (C, DC, IdentifierLocs.size() * sizeof(SourceLocation)) + return new (C, DC, + additionalSizeToAlloc<SourceLocation>(IdentifierLocs.size())) ImportDecl(DC, StartLoc, Imported, IdentifierLocs); } @@ -4066,16 +4185,15 @@ ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, Module *Imported, SourceLocation EndLoc) { - ImportDecl *Import = - new (C, DC, sizeof(SourceLocation)) ImportDecl(DC, StartLoc, - Imported, EndLoc); + ImportDecl *Import = new (C, DC, additionalSizeToAlloc<SourceLocation>(1)) + ImportDecl(DC, StartLoc, Imported, EndLoc); Import->setImplicit(); return Import; } ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumLocations) { - return new (C, ID, NumLocations * sizeof(SourceLocation)) + return new (C, ID, additionalSizeToAlloc<SourceLocation>(NumLocations)) ImportDecl(EmptyShell()); } @@ -4083,16 +4201,14 @@ ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const { if (!ImportedAndComplete.getInt()) return None; - const SourceLocation *StoredLocs - = reinterpret_cast<const SourceLocation *>(this + 1); + const auto *StoredLocs = getTrailingObjects<SourceLocation>(); return llvm::makeArrayRef(StoredLocs, getNumModuleIdentifiers(getImportedModule())); } SourceRange ImportDecl::getSourceRange() const { if (!ImportedAndComplete.getInt()) - return SourceRange(getLocation(), - *reinterpret_cast<const SourceLocation *>(this + 1)); - + return SourceRange(getLocation(), *getTrailingObjects<SourceLocation>()); + return SourceRange(getLocation(), getIdentifierLocs().back()); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index 4fcec53..72587e3 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -45,10 +45,19 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const { getASTContext().getExternalSource()->updateOutOfDateIdentifier(II); } +#define DECL(DERIVED, BASE) \ + static_assert(Decl::DeclObjAlignment >= \ + llvm::AlignOf<DERIVED##Decl>::Alignment, \ + "Alignment sufficient after objects prepended to " #DERIVED); +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" + 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. + // resulting pointer will still be 8-byte aligned. + static_assert(sizeof(unsigned) * 2 >= DeclObjAlignment, + "Decl won't be misaligned"); void *Start = Context.Allocate(Size + Extra + 8); void *Result = (char*)Start + 8; @@ -69,7 +78,13 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx, // With local visibility enabled, we track the owning module even for local // declarations. if (Ctx.getLangOpts().ModulesLocalVisibility) { - void *Buffer = ::operator new(sizeof(Module *) + Size + Extra, Ctx); + // Ensure required alignment of the resulting object by adding extra + // padding at the start if required. + size_t ExtraAlign = + llvm::OffsetToAlignment(sizeof(Module *), DeclObjAlignment); + char *Buffer = reinterpret_cast<char *>( + ::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx)); + Buffer += ExtraAlign; return new (Buffer) Module*(nullptr) + 1; } return ::operator new(Size + Extra, Ctx); @@ -251,6 +266,18 @@ void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, } } +bool Decl::isLexicallyWithinFunctionOrMethod() const { + const DeclContext *LDC = getLexicalDeclContext(); + while (true) { + if (LDC->isFunctionOrMethod()) + return true; + if (!isa<TagDecl>(LDC)) + return false; + LDC = LDC->getLexicalParent(); + } + return false; +} + bool Decl::isInAnonymousNamespace() const { const DeclContext *DC = getDeclContext(); do { @@ -542,7 +569,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Var: case ImplicitParam: case ParmVar: - case NonTypeTemplateParm: case ObjCMethod: case ObjCProperty: case MSProperty: @@ -552,6 +578,12 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case IndirectField: return IDNS_Ordinary | IDNS_Member; + case NonTypeTemplateParm: + // Non-type template parameters are not found by lookups that ignore + // non-types, but they are found by redeclaration lookups for tag types, + // so we include them in the tag namespace. + return IDNS_Ordinary | IDNS_Tag; + case ObjCCompatibleAlias: case ObjCInterface: return IDNS_Ordinary | IDNS_Type; @@ -612,6 +644,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ExternCContext: case UsingDirective: + case BuiltinTemplate: case ClassTemplateSpecialization: case ClassTemplatePartialSpecialization: case ClassScopeFunctionSpecialization: @@ -1044,14 +1077,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { // Load the external declarations, if any. SmallVector<Decl*, 64> Decls; ExternalLexicalStorage = false; - switch (Source->FindExternalLexicalDecls(this, Decls)) { - case ELR_Success: - break; - - case ELR_Failure: - case ELR_AlreadyLoaded: - return false; - } + Source->FindExternalLexicalDecls(this, Decls); if (Decls.empty()) return false; @@ -1189,13 +1215,16 @@ void DeclContext::removeDecl(Decl *D) { // Remove only decls that have a name if (!ND->getDeclName()) return; - StoredDeclsMap *Map = getPrimaryContext()->LookupPtr; - if (!Map) return; - - StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName()); - assert(Pos != Map->end() && "no lookup entry for decl"); - if (Pos->second.getAsVector() || Pos->second.getAsDecl() == ND) - Pos->second.remove(ND); + auto *DC = this; + do { + StoredDeclsMap *Map = DC->getPrimaryContext()->LookupPtr; + if (Map) { + StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName()); + assert(Pos != Map->end() && "no lookup entry for decl"); + if (Pos->second.getAsVector() || Pos->second.getAsDecl() == ND) + Pos->second.remove(ND); + } + } while (DC->isTransparentContext() && (DC = DC->getParent())); } } @@ -1213,7 +1242,7 @@ void DeclContext::addHiddenDecl(Decl *D) { } // Notify a C++ record declaration that we've added a member, so it can - // update it's class-specific state. + // update its class-specific state. if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this)) Record->addedMember(D); diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index d905fcf..4f24fdc 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -385,17 +385,11 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { } } -/// Callback function for CXXRecordDecl::forallBases that acknowledges -/// that it saw a base class. -static bool SawBase(const CXXRecordDecl *, void *) { - return true; -} - bool CXXRecordDecl::hasAnyDependentBases() const { if (!isDependentContext()) return false; - return !forallBases(SawBase, nullptr); + return !forallBases([](const CXXRecordDecl *) { return true; }); } bool CXXRecordDecl::isTriviallyCopyable() const { @@ -1224,6 +1218,10 @@ CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const { return nullptr; } +MemberSpecializationInfo *CXXRecordDecl::getMemberSpecializationInfo() const { + return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>(); +} + void CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD, TemplateSpecializationKind TSK) { @@ -1234,6 +1232,14 @@ CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD, = new (getASTContext()) MemberSpecializationInfo(RD, TSK); } +ClassTemplateDecl *CXXRecordDecl::getDescribedClassTemplate() const { + return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl *>(); +} + +void CXXRecordDecl::setDescribedClassTemplate(ClassTemplateDecl *Template) { + TemplateOrInstantiation = Template; +} + TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{ if (const ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(this)) @@ -1681,8 +1687,8 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) { - VarDecl **MyIndices = reinterpret_cast<VarDecl **> (this + 1); - memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *)); + std::uninitialized_copy(Indices, Indices + NumIndices, + getTrailingObjects<VarDecl *>()); } CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context, @@ -1692,8 +1698,7 @@ CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context, SourceLocation R, VarDecl **Indices, unsigned NumIndices) { - void *Mem = Context.Allocate(sizeof(CXXCtorInitializer) + - sizeof(VarDecl *) * NumIndices, + void *Mem = Context.Allocate(totalSizeToAlloc<VarDecl *>(NumIndices), llvm::alignOf<CXXCtorInitializer>()); return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R, Indices, NumIndices); @@ -2023,6 +2028,22 @@ NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SourceLocation(), nullptr, nullptr); } +NamespaceDecl *NamespaceDecl::getOriginalNamespace() { + if (isFirstDecl()) + return this; + + return AnonOrFirstNamespaceAndInline.getPointer(); +} + +const NamespaceDecl *NamespaceDecl::getOriginalNamespace() const { + if (isFirstDecl()) + return this; + + return AnonOrFirstNamespaceAndInline.getPointer(); +} + +bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); } + NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() { return getNextRedeclaration(); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp index a996cab..121403b 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp @@ -46,7 +46,9 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, } #endif - std::size_t Extra = FriendTypeTPLists.size() * sizeof(TemplateParameterList*); + std::size_t Extra = + FriendDecl::additionalSizeToAlloc<TemplateParameterList *>( + FriendTypeTPLists.size()); FriendDecl *FD = new (C, DC, Extra) FriendDecl(DC, L, Friend, FriendL, FriendTypeTPLists); cast<CXXRecordDecl>(DC)->pushFriendDecl(FD); @@ -55,7 +57,8 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned FriendTypeNumTPLists) { - std::size_t Extra = FriendTypeNumTPLists * sizeof(TemplateParameterList*); + std::size_t Extra = + additionalSizeToAlloc<TemplateParameterList *>(FriendTypeNumTPLists); return new (C, ID, Extra) FriendDecl(EmptyShell(), FriendTypeNumTPLists); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp index 512837f..f162e6d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp @@ -18,10 +18,8 @@ using namespace clang; DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { - static_assert(sizeof(DeclGroup) % llvm::AlignOf<void *>::Alignment == 0, - "Trailing data is unaligned!"); assert(NumDecls > 1 && "Invalid DeclGroup"); - unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls; + unsigned Size = totalSizeToAlloc<Decl *>(NumDecls); void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment); new (Mem) DeclGroup(NumDecls, Decls); return static_cast<DeclGroup*>(Mem); @@ -30,5 +28,6 @@ DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { DeclGroup::DeclGroup(unsigned numdecls, Decl** decls) : NumDecls(numdecls) { assert(numdecls > 0); assert(decls); - memcpy(this+1, decls, numdecls * sizeof(*decls)); + std::uninitialized_copy(decls, decls + numdecls, + getTrailingObjects<Decl *>()); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index 280c412..050a0f5 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -161,6 +161,15 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, return nullptr; } + // If context is class, then lookup property in its extensions. + // This comes before property is looked up in primary class. + if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) { + for (const auto *Ext : IDecl->known_extensions()) + if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext, + propertyID)) + return PD; + } + DeclContext::lookup_result R = DC->lookup(propertyID); for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) @@ -190,6 +199,15 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( if (Def->isHidden()) return nullptr; } + + // Search the extensions of a class first; they override what's in + // the class itself. + if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) { + for (const auto *Ext : ClassDecl->visible_extensions()) { + if (auto *P = Ext->FindPropertyDeclaration(PropertyId)) + return P; + } + } if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId)) @@ -207,7 +225,7 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( } case Decl::ObjCInterface: { const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this); - // Look through categories (but not extensions). + // Look through categories (but not extensions; they were handled above). for (const auto *Cat : OID->visible_categories()) { if (!Cat->IsClassExtension()) if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId)) @@ -327,6 +345,13 @@ void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM, PM[Prop->getIdentifier()] = Prop; PO.push_back(Prop); } + for (const auto *Ext : known_extensions()) { + const ObjCCategoryDecl *ClassExt = Ext; + for (auto *Prop : ClassExt->properties()) { + PM[Prop->getIdentifier()] = Prop; + PO.push_back(Prop); + } + } for (const auto *PI : all_referenced_protocols()) PI->collectPropertiesToImplement(PM, PO); // Note, the properties declared only in class extensions are still copied @@ -747,6 +772,10 @@ void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C, if (Params.empty() && SelLocs.empty()) return; + static_assert(llvm::AlignOf<ParmVarDecl *>::Alignment >= + llvm::AlignOf<SourceLocation>::Alignment, + "Alignment not sufficient for SourceLocation"); + unsigned Size = sizeof(ParmVarDecl *) * NumParams + sizeof(SourceLocation) * SelLocs.size(); ParamsAndSelLocs = C.Allocate(Size); @@ -1182,18 +1211,47 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { if (isPropertyAccessor()) { const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent()); - // If container is class extension, find its primary class. - if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(Container)) - if (CatDecl->IsClassExtension()) - Container = CatDecl->getClassInterface(); - bool IsGetter = (NumArgs == 0); - for (const auto *I : Container->properties()) { - Selector NextSel = IsGetter ? I->getGetterName() - : I->getSetterName(); - if (NextSel == Sel) - return I; + /// Local function that attempts to find a matching property within the + /// given Objective-C container. + auto findMatchingProperty = + [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * { + + for (const auto *I : Container->properties()) { + Selector NextSel = IsGetter ? I->getGetterName() + : I->getSetterName(); + if (NextSel == Sel) + return I; + } + + return nullptr; + }; + + // Look in the container we were given. + if (const auto *Found = findMatchingProperty(Container)) + return Found; + + // If we're in a category or extension, look in the main class. + const ObjCInterfaceDecl *ClassDecl = nullptr; + if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) { + ClassDecl = Category->getClassInterface(); + if (const auto *Found = findMatchingProperty(ClassDecl)) + return Found; + } else { + // Determine whether the container is a class. + ClassDecl = dyn_cast<ObjCInterfaceDecl>(Container); + } + + // If we have a class, check its visible extensions. + if (ClassDecl) { + for (const auto *Ext : ClassDecl->visible_extensions()) { + if (Ext == Container) + continue; + + if (const auto *Found = findMatchingProperty(Ext)) + return Found; + } } llvm_unreachable("Marked as a property accessor but no property found!"); @@ -1272,13 +1330,9 @@ ObjCTypeParamList *ObjCTypeParamList::create( SourceLocation lAngleLoc, ArrayRef<ObjCTypeParamDecl *> typeParams, SourceLocation rAngleLoc) { - unsigned size = sizeof(ObjCTypeParamList) - + sizeof(ObjCTypeParamDecl *) * typeParams.size(); - static_assert(llvm::AlignOf<ObjCTypeParamList>::Alignment >= - llvm::AlignOf<ObjCTypeParamDecl *>::Alignment, - "type parameter list needs greater alignment"); - unsigned align = llvm::alignOf<ObjCTypeParamList>(); - void *mem = ctx.Allocate(size, align); + void *mem = + ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()), + llvm::alignOf<ObjCTypeParamList>()); return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp index 5f8b42b..493e2cd 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp @@ -29,8 +29,9 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef<Expr *> VL) { - OMPThreadPrivateDecl *D = new (C, DC, VL.size() * sizeof(Expr *)) - OMPThreadPrivateDecl(OMPThreadPrivate, DC, L); + OMPThreadPrivateDecl *D = + new (C, DC, additionalSizeToAlloc<Expr *>(VL.size())) + OMPThreadPrivateDecl(OMPThreadPrivate, DC, L); D->NumVars = VL.size(); D->setVars(VL); return D; @@ -39,7 +40,7 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C, OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned N) { - OMPThreadPrivateDecl *D = new (C, ID, N * sizeof(Expr *)) + OMPThreadPrivateDecl *D = new (C, ID, additionalSizeToAlloc<Expr *>(N)) OMPThreadPrivateDecl(OMPThreadPrivate, nullptr, SourceLocation()); D->NumVars = N; return D; @@ -48,7 +49,6 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C, void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) { assert(VL.size() == NumVars && "Number of variables is not the same as the preallocated buffer"); - Expr **Vars = reinterpret_cast<Expr **>(this + 1); - std::copy(VL.begin(), VL.end(), Vars); + std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr *>()); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index 3202d8c..5c6002d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -96,6 +96,7 @@ namespace { void PrintTemplateParameters(const TemplateParameterList *Params, const TemplateArgumentList *Args = nullptr); void prettyPrintAttributes(Decl *D); + void prettyPrintPragmas(Decl *D); void printDeclType(QualType T, StringRef DeclName, bool Pack = false); }; } @@ -197,12 +198,40 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) { void DeclPrinter::prettyPrintAttributes(Decl *D) { if (Policy.PolishForDeclaration) return; - + + if (D->hasAttrs()) { + AttrVec &Attrs = D->getAttrs(); + for (auto *A : Attrs) { + switch (A->getKind()) { +#define ATTR(X) +#define PRAGMA_SPELLING_ATTR(X) case attr::X: +#include "clang/Basic/AttrList.inc" + break; + default: + A->printPretty(Out, Policy); + break; + } + } + } +} + +void DeclPrinter::prettyPrintPragmas(Decl *D) { + if (Policy.PolishForDeclaration) + return; + if (D->hasAttrs()) { AttrVec &Attrs = D->getAttrs(); - for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) { - Attr *A = *i; - A->printPretty(Out, Policy); + for (auto *A : Attrs) { + switch (A->getKind()) { +#define ATTR(X) +#define PRAGMA_SPELLING_ATTR(X) case attr::X: +#include "clang/Basic/AttrList.inc" + A->printPretty(Out, Policy); + Indent(); + break; + default: + break; + } } } } @@ -408,6 +437,10 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { } void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { + if (!D->getDescribedFunctionTemplate() && + !D->isFunctionTemplateSpecialization()) + prettyPrintPragmas(D); + CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D); if (!Policy.SuppressSpecifiers) { @@ -416,7 +449,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { case SC_Extern: Out << "extern "; break; case SC_Static: Out << "static "; break; case SC_PrivateExtern: Out << "__private_extern__ "; break; - case SC_Auto: case SC_Register: case SC_OpenCLWorkGroupLocal: + case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions"); } @@ -643,6 +676,7 @@ void DeclPrinter::VisitFriendDecl(FriendDecl *D) { } void DeclPrinter::VisitFieldDecl(FieldDecl *D) { + // FIXME: add printing of pragma attributes if required. if (!Policy.SuppressSpecifiers && D->isMutable()) Out << "mutable "; if (!Policy.SuppressSpecifiers && D->isModulePrivate()) @@ -672,6 +706,7 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) { } void DeclPrinter::VisitVarDecl(VarDecl *D) { + prettyPrintPragmas(D); if (!Policy.SuppressSpecifiers) { StorageClass SC = D->getStorageClass(); if (SC != SC_None) @@ -779,6 +814,7 @@ void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) { } void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { + // FIXME: add printing of pragma attributes if required. if (!Policy.SuppressSpecifiers && D->isModulePrivate()) Out << "__module_private__ "; Out << D->getKindName(); @@ -914,11 +950,13 @@ void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (PrintInstantiation) { TemplateParameterList *Params = D->getTemplateParameters(); for (auto *I : D->specializations()) { + prettyPrintPragmas(I); PrintTemplateParameters(Params, I->getTemplateSpecializationArgs()); Visit(I); } } + prettyPrintPragmas(D->getTemplatedDecl()); return VisitRedeclarableTemplateDecl(D); } @@ -1088,7 +1126,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { } if (SID) - Out << " : " << OID->getSuperClass()->getName(); + Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy); // Protocols? const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); @@ -1299,7 +1337,7 @@ void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { if (!D->isAccessDeclaration()) Out << "using "; D->getQualifier()->print(Out, Policy); - Out << D->getName(); + Out << D->getDeclName(); } void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index cde497b..de3ebd2 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -18,6 +18,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/STLExtras.h" #include <memory> @@ -29,10 +30,10 @@ using namespace clang; TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, - NamedDecl **Params, unsigned NumParams, + ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc) : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc), - NumParams(NumParams), ContainsUnexpandedParameterPack(false) { + NumParams(Params.size()), ContainsUnexpandedParameterPack(false) { assert(this->NumParams == NumParams && "Too many template parameters"); for (unsigned Idx = 0; Idx < NumParams; ++Idx) { NamedDecl *P = Params[Idx]; @@ -53,17 +54,13 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, } } -TemplateParameterList * -TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, NamedDecl **Params, - unsigned NumParams, SourceLocation RAngleLoc) { - unsigned Size = sizeof(TemplateParameterList) - + sizeof(NamedDecl *) * NumParams; - unsigned Align = std::max(llvm::alignOf<TemplateParameterList>(), - llvm::alignOf<NamedDecl*>()); - void *Mem = C.Allocate(Size, Align); +TemplateParameterList *TemplateParameterList::Create( + const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, + ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc) { + void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *>(Params.size()), + llvm::alignOf<TemplateParameterList>()); return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params, - NumParams, RAngleLoc); + RAngleLoc); } unsigned TemplateParameterList::getMinRequiredArguments() const { @@ -240,8 +237,8 @@ static void GenerateInjectedTemplateArgs(ASTContext &Context, } if ((*Param)->isTemplateParameterPack()) - Arg = TemplateArgument::CreatePackCopy(Context, &Arg, 1); - + Arg = TemplateArgument::CreatePackCopy(Context, Arg); + *Args++ = Arg; } } @@ -552,10 +549,11 @@ NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC, TemplateParmPosition(D, P), ParameterPack(true), ExpandedParameterPack(true), NumExpandedTypes(NumExpandedTypes) { if (ExpandedTypes && ExpandedTInfos) { - void **TypesAndInfos = reinterpret_cast<void **>(this + 1); + auto TypesAndInfos = + getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>(); for (unsigned I = 0; I != NumExpandedTypes; ++I) { - TypesAndInfos[2*I] = ExpandedTypes[I].getAsOpaquePtr(); - TypesAndInfos[2*I + 1] = ExpandedTInfos[I]; + new (&TypesAndInfos[I].first) QualType(ExpandedTypes[I]); + TypesAndInfos[I].second = ExpandedTInfos[I]; } } } @@ -579,10 +577,11 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, const QualType *ExpandedTypes, unsigned NumExpandedTypes, TypeSourceInfo **ExpandedTInfos) { - unsigned Extra = NumExpandedTypes * 2 * sizeof(void*); - return new (C, DC, Extra) NonTypeTemplateParmDecl( - DC, StartLoc, IdLoc, D, P, Id, T, TInfo, - ExpandedTypes, NumExpandedTypes, ExpandedTInfos); + return new (C, DC, + additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>( + NumExpandedTypes)) + NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo, + ExpandedTypes, NumExpandedTypes, ExpandedTInfos); } NonTypeTemplateParmDecl * @@ -595,10 +594,12 @@ NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { NonTypeTemplateParmDecl * NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumExpandedTypes) { - unsigned Extra = NumExpandedTypes * 2 * sizeof(void*); - return new (C, ID, Extra) NonTypeTemplateParmDecl( - nullptr, SourceLocation(), SourceLocation(), 0, 0, nullptr, QualType(), - nullptr, nullptr, NumExpandedTypes, nullptr); + return new (C, ID, + additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>( + NumExpandedTypes)) + NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(), 0, 0, + nullptr, QualType(), nullptr, nullptr, + NumExpandedTypes, nullptr); } SourceRange NonTypeTemplateParmDecl::getSourceRange() const { @@ -628,8 +629,8 @@ TemplateTemplateParmDecl::TemplateTemplateParmDecl( TemplateParmPosition(D, P), ParameterPack(true), ExpandedParameterPack(true), NumExpandedParams(NumExpansions) { if (Expansions) - std::memcpy(reinterpret_cast<void*>(this + 1), Expansions, - sizeof(TemplateParameterList*) * NumExpandedParams); + std::uninitialized_copy(Expansions, Expansions + NumExpandedParams, + getTrailingObjects<TemplateParameterList *>()); } TemplateTemplateParmDecl * @@ -647,9 +648,10 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, IdentifierInfo *Id, TemplateParameterList *Params, ArrayRef<TemplateParameterList *> Expansions) { - return new (C, DC, sizeof(TemplateParameterList*) * Expansions.size()) - TemplateTemplateParmDecl(DC, L, D, P, Id, Params, - Expansions.size(), Expansions.data()); + return new (C, DC, + additionalSizeToAlloc<TemplateParameterList *>(Expansions.size())) + TemplateTemplateParmDecl(DC, L, D, P, Id, Params, Expansions.size(), + Expansions.data()); } TemplateTemplateParmDecl * @@ -661,7 +663,8 @@ TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { TemplateTemplateParmDecl * TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumExpansions) { - return new (C, ID, sizeof(TemplateParameterList*) * NumExpansions) + return new (C, ID, + additionalSizeToAlloc<TemplateParameterList *>(NumExpansions)) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr, nullptr, NumExpansions, nullptr); } @@ -682,18 +685,19 @@ void TemplateTemplateParmDecl::setDefaultArgument( //===----------------------------------------------------------------------===// // TemplateArgumentList Implementation //===----------------------------------------------------------------------===// +TemplateArgumentList::TemplateArgumentList(const TemplateArgument *Args, + unsigned NumArgs) + : Arguments(getTrailingObjects<TemplateArgument>()), NumArguments(NumArgs) { + std::uninitialized_copy(Args, Args + NumArgs, + getTrailingObjects<TemplateArgument>()); +} + TemplateArgumentList * TemplateArgumentList::CreateCopy(ASTContext &Context, const TemplateArgument *Args, unsigned NumArgs) { - std::size_t Size = sizeof(TemplateArgumentList) - + NumArgs * sizeof(TemplateArgument); - void *Mem = Context.Allocate(Size); - TemplateArgument *StoredArgs - = reinterpret_cast<TemplateArgument *>( - static_cast<TemplateArgumentList *>(Mem) + 1); - std::uninitialized_copy(Args, Args + NumArgs, StoredArgs); - return new (Mem) TemplateArgumentList(StoredArgs, NumArgs, true); + void *Mem = Context.Allocate(totalSizeToAlloc<TemplateArgument>(NumArgs)); + return new (Mem) TemplateArgumentList(Args, NumArgs); } FunctionTemplateSpecializationInfo * @@ -1187,3 +1191,69 @@ VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) VarTemplatePartialSpecializationDecl(C); } + +static TemplateParameterList * +createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { + // typename T + auto *T = TemplateTypeParmDecl::Create( + C, DC, SourceLocation(), SourceLocation(), /*Depth=*/1, /*Position=*/0, + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false); + T->setImplicit(true); + + // T ...Ints + TypeSourceInfo *TI = + C.getTrivialTypeSourceInfo(QualType(T->getTypeForDecl(), 0)); + auto *N = NonTypeTemplateParmDecl::Create( + C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, + /*Id=*/nullptr, TI->getType(), /*ParameterPack=*/true, TI); + N->setImplicit(true); + + // <typename T, T ...Ints> + NamedDecl *P[2] = {T, N}; + auto *TPL = TemplateParameterList::Create( + C, SourceLocation(), SourceLocation(), P, SourceLocation()); + + // template <typename T, ...Ints> class IntSeq + auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create( + C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0, + /*ParameterPack=*/false, /*Id=*/nullptr, TPL); + TemplateTemplateParm->setImplicit(true); + + // typename T + auto *TemplateTypeParm = TemplateTypeParmDecl::Create( + C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false); + TemplateTypeParm->setImplicit(true); + + // T N + TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo( + QualType(TemplateTypeParm->getTypeForDecl(), 0)); + auto *NonTypeTemplateParm = NonTypeTemplateParmDecl::Create( + C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/2, + /*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo); + NamedDecl *Params[] = {TemplateTemplateParm, TemplateTypeParm, + NonTypeTemplateParm}; + + // template <template <typename T, T ...Ints> class IntSeq, typename T, T N> + return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), + Params, SourceLocation()); +} + +static TemplateParameterList *createBuiltinTemplateParameterList( + const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) { + switch (BTK) { + case BTK__make_integer_seq: + return createMakeIntegerSeqParameterList(C, DC); + } + + llvm_unreachable("unhandled BuiltinTemplateKind!"); +} + +void BuiltinTemplateDecl::anchor() {} + +BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC, + DeclarationName Name, + BuiltinTemplateKind BTK) + : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name, + createBuiltinTemplateParameterList(C, DC, BTK)), + BTK(BTK) {} diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp index b7c2877..b2f2727 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp @@ -182,7 +182,7 @@ raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { } case DeclarationName::CXXLiteralOperatorName: - return OS << "operator \"\" " << N.getCXXLiteralIdentifier()->getName(); + return OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName(); case DeclarationName::CXXConversionFunctionName: { OS << "operator "; diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 2e066b2..52f34df 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -331,7 +331,8 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, D(D), Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) { DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0; if (QualifierLoc) { - getInternalQualifierLoc() = QualifierLoc; + new (getTrailingObjects<NestedNameSpecifierLoc>()) + NestedNameSpecifierLoc(QualifierLoc); auto *NNS = QualifierLoc.getNestedNameSpecifier(); if (NNS->isInstantiationDependent()) ExprBits.InstantiationDependent = true; @@ -340,7 +341,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, } DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0; if (FoundD) - getInternalFoundDecl() = FoundD; + *getTrailingObjects<NamedDecl *>() = FoundD; DeclRefExprBits.HasTemplateKWAndArgsInfo = (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0; DeclRefExprBits.RefersToEnclosingVariableOrCapture = @@ -349,15 +350,15 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, bool Dependent = false; bool InstantiationDependent = false; bool ContainsUnexpandedParameterPack = false; - getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs, - Dependent, - InstantiationDependent, - ContainsUnexpandedParameterPack); + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( + TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(), + Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); assert(!Dependent && "built a DeclRefExpr with dependent template args"); ExprBits.InstantiationDependent |= InstantiationDependent; ExprBits.ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack; } else if (TemplateKWLoc.isValid()) { - getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( + TemplateKWLoc); } DeclRefExprBits.HadMultipleCandidates = 0; @@ -394,15 +395,13 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context, if (D == FoundD) FoundD = nullptr; - std::size_t Size = sizeof(DeclRefExpr); - if (QualifierLoc) - Size += sizeof(NestedNameSpecifierLoc); - if (FoundD) - Size += sizeof(NamedDecl *); - if (TemplateArgs) - Size += ASTTemplateKWAndArgsInfo::sizeFor(TemplateArgs->size()); - else if (TemplateKWLoc.isValid()) - Size += ASTTemplateKWAndArgsInfo::sizeFor(0); + bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); + std::size_t Size = + totalSizeToAlloc<NestedNameSpecifierLoc, NamedDecl *, + ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( + QualifierLoc ? 1 : 0, FoundD ? 1 : 0, + HasTemplateKWAndArgsInfo ? 1 : 0, + TemplateArgs ? TemplateArgs->size() : 0); void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D, @@ -415,14 +414,12 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context, bool HasFoundDecl, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { - std::size_t Size = sizeof(DeclRefExpr); - if (HasQualifier) - Size += sizeof(NestedNameSpecifierLoc); - if (HasFoundDecl) - Size += sizeof(NamedDecl *); - if (HasTemplateKWAndArgsInfo) - Size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); - + assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); + std::size_t Size = + totalSizeToAlloc<NestedNameSpecifierLoc, NamedDecl *, + ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( + HasQualifier ? 1 : 0, HasFoundDecl ? 1 : 0, HasTemplateKWAndArgsInfo, + NumTemplateArgs); void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); return new (Mem) DeclRefExpr(EmptyShell()); } @@ -490,7 +487,6 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { else MC->mangleName(ND, Out); - Out.flush(); if (!Buffer.empty() && Buffer.front() == '\01') return Buffer.substr(1); return Buffer.str(); @@ -652,7 +648,6 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { Out << Proto; - Out.flush(); return Name.str().str(); } if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(CurrentDecl)) { @@ -684,7 +679,6 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { MD->getSelector().print(Out); Out << ']'; - Out.flush(); return Name.str().str(); } if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) { @@ -1002,15 +996,33 @@ void StringLiteral::setString(const ASTContext &C, StringRef Str, /// can have escape sequences in them in addition to the usual trigraph and /// escaped newline business. This routine handles this complexity. /// -SourceLocation StringLiteral:: -getLocationOfByte(unsigned ByteNo, const SourceManager &SM, - const LangOptions &Features, const TargetInfo &Target) const { +/// The *StartToken sets the first token to be searched in this function and +/// the *StartTokenByteOffset is the byte offset of the first token. Before +/// returning, it updates the *StartToken to the TokNo of the token being found +/// and sets *StartTokenByteOffset to the byte offset of the token in the +/// string. +/// Using these two parameters can reduce the time complexity from O(n^2) to +/// O(n) if one wants to get the location of byte for all the tokens in a +/// string. +/// +SourceLocation +StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, + const LangOptions &Features, + const TargetInfo &Target, unsigned *StartToken, + unsigned *StartTokenByteOffset) const { assert((Kind == StringLiteral::Ascii || Kind == StringLiteral::UTF8) && "Only narrow string literals are currently supported"); // Loop over all of the tokens in this string until we find the one that // contains the byte we're looking for. unsigned TokNo = 0; + unsigned StringOffset = 0; + if (StartToken) + TokNo = *StartToken; + if (StartTokenByteOffset) { + StringOffset = *StartTokenByteOffset; + ByteNo -= StringOffset; + } while (1) { assert(TokNo < getNumConcatenated() && "Invalid byte number!"); SourceLocation StrTokLoc = getStrTokenLoc(TokNo); @@ -1019,14 +1031,20 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM, // the string literal, not the identifier for the macro it is potentially // expanded through. SourceLocation StrTokSpellingLoc = SM.getSpellingLoc(StrTokLoc); - + // Re-lex the token to get its length and original spelling. - std::pair<FileID, unsigned> LocInfo =SM.getDecomposedLoc(StrTokSpellingLoc); + std::pair<FileID, unsigned> LocInfo = + SM.getDecomposedLoc(StrTokSpellingLoc); bool Invalid = false; StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); - if (Invalid) + if (Invalid) { + if (StartTokenByteOffset != nullptr) + *StartTokenByteOffset = StringOffset; + if (StartToken != nullptr) + *StartToken = TokNo; return StrTokSpellingLoc; - + } + const char *StrData = Buffer.data()+LocInfo.second; // Create a lexer starting at the beginning of this token. @@ -1042,14 +1060,19 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM, // If the byte is in this token, return the location of the byte. if (ByteNo < TokNumBytes || (ByteNo == TokNumBytes && TokNo == getNumConcatenated() - 1)) { - unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo); - + unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo); + // Now that we know the offset of the token in the spelling, use the // preprocessor to get the offset in the original source. + if (StartTokenByteOffset != nullptr) + *StartTokenByteOffset = StringOffset; + if (StartToken != nullptr) + *StartToken = TokNo; return Lexer::AdvanceToTokenCharacter(StrTokLoc, Offset, SM, Features); } - + // Move to the next string token. + StringOffset += TokNumBytes; ++TokNo; ByteNo -= TokNumBytes; } @@ -1074,6 +1097,7 @@ StringRef UnaryOperator::getOpcodeStr(Opcode Op) { case UO_Real: return "__real"; case UO_Imag: return "__imag"; case UO_Extension: return "__extension__"; + case UO_Coawait: return "co_await"; } llvm_unreachable("Unknown unary operator"); } @@ -1090,6 +1114,7 @@ UnaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix) { case OO_Minus: return UO_Minus; case OO_Tilde: return UO_Not; case OO_Exclaim: return UO_LNot; + case OO_Coawait: return UO_Coawait; } } @@ -1103,6 +1128,7 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) { case UO_Minus: return OO_Minus; case UO_Not: return OO_Tilde; case UO_LNot: return OO_Exclaim; + case UO_Coawait: return OO_Coawait; default: return OO_None; } } @@ -1288,9 +1314,8 @@ OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type, ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs, SourceLocation RParenLoc) { - void *Mem = C.Allocate(sizeof(OffsetOfExpr) + - sizeof(OffsetOfNode) * comps.size() + - sizeof(Expr*) * exprs.size()); + void *Mem = C.Allocate( + totalSizeToAlloc<OffsetOfNode, Expr *>(comps.size(), exprs.size())); return new (Mem) OffsetOfExpr(C, type, OperatorLoc, tsi, comps, exprs, RParenLoc); @@ -1298,9 +1323,8 @@ OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type, OffsetOfExpr *OffsetOfExpr::CreateEmpty(const ASTContext &C, unsigned numComps, unsigned numExprs) { - void *Mem = C.Allocate(sizeof(OffsetOfExpr) + - sizeof(OffsetOfNode) * numComps + - sizeof(Expr*) * numExprs); + void *Mem = + C.Allocate(totalSizeToAlloc<OffsetOfNode, Expr *>(numComps, numExprs)); return new (Mem) OffsetOfExpr(numComps, numExprs); } @@ -1330,7 +1354,7 @@ OffsetOfExpr::OffsetOfExpr(const ASTContext &C, QualType type, } } -IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const { +IdentifierInfo *OffsetOfNode::getFieldName() const { assert(getKind() == Field || getKind() == Identifier); if (getKind() == Field) return getField()->getIdentifier(); @@ -1382,18 +1406,17 @@ MemberExpr *MemberExpr::Create( ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs, QualType ty, ExprValueKind vk, ExprObjectKind ok) { - std::size_t Size = sizeof(MemberExpr); bool hasQualOrFound = (QualifierLoc || founddecl.getDecl() != memberdecl || founddecl.getAccess() != memberdecl->getAccess()); - if (hasQualOrFound) - Size += sizeof(MemberNameQualifier); - if (targs) - Size += ASTTemplateKWAndArgsInfo::sizeFor(targs->size()); - else if (TemplateKWLoc.isValid()) - Size += ASTTemplateKWAndArgsInfo::sizeFor(0); + bool HasTemplateKWAndArgsInfo = targs || TemplateKWLoc.isValid(); + std::size_t Size = + totalSizeToAlloc<MemberExprNameQualifier, ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc>(hasQualOrFound ? 1 : 0, + HasTemplateKWAndArgsInfo ? 1 : 0, + targs ? targs->size() : 0); void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>()); MemberExpr *E = new (Mem) @@ -1412,7 +1435,8 @@ MemberExpr *MemberExpr::Create( E->HasQualifierOrFoundDecl = true; - MemberNameQualifier *NQ = E->getMemberQualifier(); + MemberExprNameQualifier *NQ = + E->getTrailingObjects<MemberExprNameQualifier>(); NQ->QualifierLoc = QualifierLoc; NQ->FoundDecl = founddecl; } @@ -1423,14 +1447,14 @@ MemberExpr *MemberExpr::Create( bool Dependent = false; bool InstantiationDependent = false; bool ContainsUnexpandedParameterPack = false; - E->getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *targs, - Dependent, - InstantiationDependent, - ContainsUnexpandedParameterPack); + E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( + TemplateKWLoc, *targs, E->getTrailingObjects<TemplateArgumentLoc>(), + Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); if (InstantiationDependent) E->setInstantiationDependent(true); } else if (TemplateKWLoc.isValid()) { - E->getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); + E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( + TemplateKWLoc); } return E; @@ -1529,6 +1553,7 @@ bool CastExpr::CastConsistency() const { case CK_ToVoid: case CK_VectorSplat: case CK_IntegralCast: + case CK_BooleanToSignedIntegral: case CK_IntegralToFloating: case CK_FloatingToIntegral: case CK_FloatingCast: @@ -1622,6 +1647,8 @@ const char *CastExpr::getCastKindName() const { return "VectorSplat"; case CK_IntegralCast: return "IntegralCast"; + case CK_BooleanToSignedIntegral: + return "BooleanToSignedIntegral"; case CK_IntegralToBoolean: return "IntegralToBoolean"; case CK_IntegralToFloating: @@ -1719,9 +1746,9 @@ Expr *CastExpr::getSubExprAsWritten() { CXXBaseSpecifier **CastExpr::path_buffer() { switch (getStmtClass()) { #define ABSTRACT_STMT(x) -#define CASTEXPR(Type, Base) \ - case Stmt::Type##Class: \ - return reinterpret_cast<CXXBaseSpecifier**>(static_cast<Type*>(this)+1); +#define CASTEXPR(Type, Base) \ + case Stmt::Type##Class: \ + return static_cast<Type *>(this)->getTrailingObjects<CXXBaseSpecifier *>(); #define STMT(Type, Base) #include "clang/AST/StmtNodes.inc" default: @@ -1729,28 +1756,23 @@ CXXBaseSpecifier **CastExpr::path_buffer() { } } -void CastExpr::setCastPath(const CXXCastPath &Path) { - assert(Path.size() == path_size()); - memcpy(path_buffer(), Path.data(), Path.size() * sizeof(CXXBaseSpecifier*)); -} - ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind VK) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = - C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); ImplicitCastExpr *E = new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK); - if (PathSize) E->setCastPath(*BasePath); + if (PathSize) + std::uninitialized_copy_n(BasePath->data(), BasePath->size(), + E->getTrailingObjects<CXXBaseSpecifier *>()); return E; } ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = - C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize); } @@ -1761,18 +1783,18 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = - C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); CStyleCastExpr *E = new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R); - if (PathSize) E->setCastPath(*BasePath); + if (PathSize) + std::uninitialized_copy_n(BasePath->data(), BasePath->size(), + E->getTrailingObjects<CXXBaseSpecifier *>()); return E; } CStyleCastExpr *CStyleCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = - C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize); } @@ -2045,6 +2067,9 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, case UO_LNot: case UO_Deref: break; + case UO_Coawait: + // This is just the 'operator co_await' call inside the guts of a + // dependent co_await call. case UO_PostInc: case UO_PostDec: case UO_PreInc: @@ -2880,7 +2905,10 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, return cast<CXXDefaultInitExpr>(this)->getExpr() ->isConstantInitializer(Ctx, false, Culprit); } - if (isEvaluatable(Ctx)) + // Allow certain forms of UB in constant initializers: signed integer + // overflow and floating-point division by zero. We'll give a warning on + // these, but they're common enough that we have to accept them. + if (isEvaluatable(Ctx, SE_AllowUndefinedBehavior)) return true; if (Culprit) *Culprit = this; @@ -2993,6 +3021,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, return true; case MSPropertyRefExprClass: + case MSPropertySubscriptExprClass: case CompoundAssignOperatorClass: case VAArgExprClass: case AtomicExprClass: @@ -3000,6 +3029,8 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case CXXNewExprClass: case CXXDeleteExprClass: case ExprWithCleanupsClass: + case CoawaitExprClass: + case CoyieldExprClass: // These always have a side-effect. return true; @@ -3012,6 +3043,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case ParenExprClass: case ArraySubscriptExprClass: + case OMPArraySectionExprClass: case MemberExprClass: case ConditionalOperatorClass: case BinaryConditionalOperatorClass: @@ -3246,9 +3278,20 @@ Expr::isNullPointerConstant(ASTContext &Ctx, // Check that it is a cast to void*. if (const PointerType *PT = CE->getType()->getAs<PointerType>()) { QualType Pointee = PT->getPointeeType(); - if (!Pointee.hasQualifiers() && - Pointee->isVoidType() && // to void* - CE->getSubExpr()->getType()->isIntegerType()) // from int. + Qualifiers Q = Pointee.getQualifiers(); + // In OpenCL v2.0 generic address space acts as a placeholder + // and should be ignored. + bool IsASValid = true; + if (Ctx.getLangOpts().OpenCLVersion >= 200) { + if (Pointee.getAddressSpace() == LangAS::opencl_generic) + Q.removeAddressSpace(); + else + IsASValid = false; + } + + if (IsASValid && !Q.hasQualifiers() && + Pointee->isVoidType() && // to void* + CE->getSubExpr()->getType()->isIntegerType()) // from int. return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC); } } @@ -3429,6 +3472,18 @@ bool Expr::refersToVectorElement() const { return false; } +bool Expr::refersToGlobalRegisterVar() const { + const Expr *E = this->IgnoreParenImpCasts(); + + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) + if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) + if (VD->getStorageClass() == SC_Register && + VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl()) + return true; + + return false; +} + /// isArrow - Return true if the base expression is a pointer to vector, /// return false if the base expression is a vector. bool ExtVectorElementExpr::isArrow() const { @@ -3464,7 +3519,7 @@ bool ExtVectorElementExpr::containsDuplicateElements() const { /// getEncodedElementAccess - We encode the fields as a llvm ConstantArray. void ExtVectorElementExpr::getEncodedElementAccess( - SmallVectorImpl<unsigned> &Elts) const { + SmallVectorImpl<uint32_t> &Elts) const { StringRef Comp = Accessor->getName(); if (Comp[0] == 's' || Comp[0] == 'S') Comp = Comp.substr(1); @@ -3492,285 +3547,6 @@ void ExtVectorElementExpr::getEncodedElementAccess( } } -ObjCMessageExpr::ObjCMessageExpr(QualType T, - ExprValueKind VK, - SourceLocation LBracLoc, - SourceLocation SuperLoc, - bool IsInstanceSuper, - QualType SuperType, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - SelectorLocationsKind SelLocsK, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit) - : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, - /*TypeDependent=*/false, /*ValueDependent=*/false, - /*InstantiationDependent=*/false, - /*ContainsUnexpandedParameterPack=*/false), - SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method - : Sel.getAsOpaquePtr())), - Kind(IsInstanceSuper? SuperInstance : SuperClass), - HasMethod(Method != nullptr), IsDelegateInitCall(false), - IsImplicit(isImplicit), SuperLoc(SuperLoc), LBracLoc(LBracLoc), - RBracLoc(RBracLoc) -{ - initArgsAndSelLocs(Args, SelLocs, SelLocsK); - setReceiverPointer(SuperType.getAsOpaquePtr()); -} - -ObjCMessageExpr::ObjCMessageExpr(QualType T, - ExprValueKind VK, - SourceLocation LBracLoc, - TypeSourceInfo *Receiver, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - SelectorLocationsKind SelLocsK, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit) - : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(), - T->isDependentType(), T->isInstantiationDependentType(), - T->containsUnexpandedParameterPack()), - SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method - : Sel.getAsOpaquePtr())), - Kind(Class), - HasMethod(Method != nullptr), IsDelegateInitCall(false), - IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) -{ - initArgsAndSelLocs(Args, SelLocs, SelLocsK); - setReceiverPointer(Receiver); -} - -ObjCMessageExpr::ObjCMessageExpr(QualType T, - ExprValueKind VK, - SourceLocation LBracLoc, - Expr *Receiver, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - SelectorLocationsKind SelLocsK, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit) - : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(), - Receiver->isTypeDependent(), - Receiver->isInstantiationDependent(), - Receiver->containsUnexpandedParameterPack()), - SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method - : Sel.getAsOpaquePtr())), - Kind(Instance), - HasMethod(Method != nullptr), IsDelegateInitCall(false), - IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) -{ - initArgsAndSelLocs(Args, SelLocs, SelLocsK); - setReceiverPointer(Receiver); -} - -void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args, - ArrayRef<SourceLocation> SelLocs, - SelectorLocationsKind SelLocsK) { - setNumArgs(Args.size()); - Expr **MyArgs = getArgs(); - for (unsigned I = 0; I != Args.size(); ++I) { - if (Args[I]->isTypeDependent()) - ExprBits.TypeDependent = true; - if (Args[I]->isValueDependent()) - ExprBits.ValueDependent = true; - if (Args[I]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (Args[I]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - - MyArgs[I] = Args[I]; - } - - SelLocsKind = SelLocsK; - if (!isImplicit()) { - if (SelLocsK == SelLoc_NonStandard) - std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs()); - } -} - -ObjCMessageExpr *ObjCMessageExpr::Create(const ASTContext &Context, QualType T, - ExprValueKind VK, - SourceLocation LBracLoc, - SourceLocation SuperLoc, - bool IsInstanceSuper, - QualType SuperType, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit) { - assert((!SelLocs.empty() || isImplicit) && - "No selector locs for non-implicit message"); - ObjCMessageExpr *Mem; - SelectorLocationsKind SelLocsK = SelectorLocationsKind(); - if (isImplicit) - Mem = alloc(Context, Args.size(), 0); - else - Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); - return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper, - SuperType, Sel, SelLocs, SelLocsK, - Method, Args, RBracLoc, isImplicit); -} - -ObjCMessageExpr *ObjCMessageExpr::Create(const ASTContext &Context, QualType T, - ExprValueKind VK, - SourceLocation LBracLoc, - TypeSourceInfo *Receiver, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit) { - assert((!SelLocs.empty() || isImplicit) && - "No selector locs for non-implicit message"); - ObjCMessageExpr *Mem; - SelectorLocationsKind SelLocsK = SelectorLocationsKind(); - if (isImplicit) - Mem = alloc(Context, Args.size(), 0); - else - Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); - return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, - SelLocs, SelLocsK, Method, Args, RBracLoc, - isImplicit); -} - -ObjCMessageExpr *ObjCMessageExpr::Create(const ASTContext &Context, QualType T, - ExprValueKind VK, - SourceLocation LBracLoc, - Expr *Receiver, - Selector Sel, - ArrayRef<SourceLocation> SelLocs, - ObjCMethodDecl *Method, - ArrayRef<Expr *> Args, - SourceLocation RBracLoc, - bool isImplicit) { - assert((!SelLocs.empty() || isImplicit) && - "No selector locs for non-implicit message"); - ObjCMessageExpr *Mem; - SelectorLocationsKind SelLocsK = SelectorLocationsKind(); - if (isImplicit) - Mem = alloc(Context, Args.size(), 0); - else - Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); - return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, - SelLocs, SelLocsK, Method, Args, RBracLoc, - isImplicit); -} - -ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(const ASTContext &Context, - unsigned NumArgs, - unsigned NumStoredSelLocs) { - ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs); - return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); -} - -ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, - ArrayRef<Expr *> Args, - SourceLocation RBraceLoc, - ArrayRef<SourceLocation> SelLocs, - Selector Sel, - SelectorLocationsKind &SelLocsK) { - SelLocsK = hasStandardSelectorLocs(Sel, SelLocs, Args, RBraceLoc); - unsigned NumStoredSelLocs = (SelLocsK == SelLoc_NonStandard) ? SelLocs.size() - : 0; - return alloc(C, Args.size(), NumStoredSelLocs); -} - -ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, - unsigned NumArgs, - unsigned NumStoredSelLocs) { - unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + - NumArgs * sizeof(Expr *) + NumStoredSelLocs * sizeof(SourceLocation); - return (ObjCMessageExpr *)C.Allocate(Size, - llvm::AlignOf<ObjCMessageExpr>::Alignment); -} - -void ObjCMessageExpr::getSelectorLocs( - SmallVectorImpl<SourceLocation> &SelLocs) const { - for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i) - SelLocs.push_back(getSelectorLoc(i)); -} - -SourceRange ObjCMessageExpr::getReceiverRange() const { - switch (getReceiverKind()) { - case Instance: - return getInstanceReceiver()->getSourceRange(); - - case Class: - return getClassReceiverTypeInfo()->getTypeLoc().getSourceRange(); - - case SuperInstance: - case SuperClass: - return getSuperLoc(); - } - - llvm_unreachable("Invalid ReceiverKind!"); -} - -Selector ObjCMessageExpr::getSelector() const { - if (HasMethod) - return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod) - ->getSelector(); - return Selector(SelectorOrMethod); -} - -QualType ObjCMessageExpr::getReceiverType() const { - switch (getReceiverKind()) { - case Instance: - return getInstanceReceiver()->getType(); - case Class: - return getClassReceiver(); - case SuperInstance: - case SuperClass: - return getSuperType(); - } - - llvm_unreachable("unexpected receiver kind"); -} - -ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { - QualType T = getReceiverType(); - - if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>()) - return Ptr->getInterfaceDecl(); - - if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>()) - return Ty->getInterface(); - - return nullptr; -} - -QualType ObjCPropertyRefExpr::getReceiverType(const ASTContext &ctx) const { - if (isClassReceiver()) - return ctx.getObjCInterfaceType(getClassReceiver()); - - if (isSuperReceiver()) - return getSuperReceiverType(); - - return getBase()->getType(); -} - -StringRef ObjCBridgedCastExpr::getBridgeKindName() const { - switch (getBridgeKind()) { - case OBC_Bridge: - return "__bridge"; - case OBC_BridgeTransfer: - return "__bridge_transfer"; - case OBC_BridgeRetained: - return "__bridge_retained"; - } - - llvm_unreachable("Invalid BridgeKind!"); -} - ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, QualType Type, SourceLocation BLoc, SourceLocation RP) @@ -3883,7 +3659,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, this->Designators = new (C) Designator[NumDesignators]; // Record the initializer itself. - child_range Child = children(); + child_iterator Child = child_begin(); *Child++ = Init; // Copy the designators and their subexpressions, computing @@ -3938,8 +3714,8 @@ DesignatedInitExpr::Create(const ASTContext &C, Designator *Designators, ArrayRef<Expr*> IndexExprs, SourceLocation ColonOrEqualLoc, bool UsesColonSyntax, Expr *Init) { - void *Mem = C.Allocate(sizeof(DesignatedInitExpr) + - sizeof(Stmt *) * (IndexExprs.size() + 1), 8); + void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(IndexExprs.size() + 1), + llvm::alignOf<DesignatedInitExpr>()); return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators, ColonOrEqualLoc, UsesColonSyntax, IndexExprs, Init); @@ -3947,8 +3723,8 @@ DesignatedInitExpr::Create(const ASTContext &C, Designator *Designators, DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(const ASTContext &C, unsigned NumIndexExprs) { - void *Mem = C.Allocate(sizeof(DesignatedInitExpr) + - sizeof(Stmt *) * (NumIndexExprs + 1), 8); + void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(NumIndexExprs + 1), + llvm::alignOf<DesignatedInitExpr>()); return new (Mem) DesignatedInitExpr(NumIndexExprs + 1); } @@ -3990,22 +3766,19 @@ SourceLocation DesignatedInitExpr::getLocEnd() const { Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) const { assert(D.Kind == Designator::ArrayDesignator && "Requires array designator"); - Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1); - return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1)); + return getSubExpr(D.ArrayOrRange.Index + 1); } Expr *DesignatedInitExpr::getArrayRangeStart(const Designator &D) const { assert(D.Kind == Designator::ArrayRangeDesignator && "Requires array range designator"); - Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1); - return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1)); + return getSubExpr(D.ArrayOrRange.Index + 1); } Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator &D) const { assert(D.Kind == Designator::ArrayRangeDesignator && "Requires array range designator"); - Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1); - return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2)); + return getSubExpr(D.ArrayOrRange.Index + 2); } /// \brief Replaces the designator at index @p Idx with the series @@ -4089,9 +3862,9 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &Context, EmptyShell sh, unsigned numSemanticExprs) { - void *buffer = Context.Allocate(sizeof(PseudoObjectExpr) + - (1 + numSemanticExprs) * sizeof(Expr*), - llvm::alignOf<PseudoObjectExpr>()); + void *buffer = + Context.Allocate(totalSizeToAlloc<Expr *>(1 + numSemanticExprs), + llvm::alignOf<PseudoObjectExpr>()); return new(buffer) PseudoObjectExpr(sh, numSemanticExprs); } @@ -4118,8 +3891,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax, assert(semantics[resultIndex]->getObjectKind() == OK_Ordinary); } - void *buffer = C.Allocate(sizeof(PseudoObjectExpr) + - (1 + semantics.size()) * sizeof(Expr*), + void *buffer = C.Allocate(totalSizeToAlloc<Expr *>(semantics.size() + 1), llvm::alignOf<PseudoObjectExpr>()); return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics, resultIndex); @@ -4154,19 +3926,6 @@ PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK, } //===----------------------------------------------------------------------===// -// ExprIterator. -//===----------------------------------------------------------------------===// - -Expr* ExprIterator::operator[](size_t idx) { return cast<Expr>(I[idx]); } -Expr* ExprIterator::operator*() const { return cast<Expr>(*I); } -Expr* ExprIterator::operator->() const { return cast<Expr>(*I); } -const Expr* ConstExprIterator::operator[](size_t idx) const { - return cast<Expr>(I[idx]); -} -const Expr* ConstExprIterator::operator*() const { return cast<Expr>(*I); } -const Expr* ConstExprIterator::operator->() const { return cast<Expr>(*I); } - -//===----------------------------------------------------------------------===// // Child Iterators for iterating over subexpressions/substatements //===----------------------------------------------------------------------===// @@ -4179,134 +3938,11 @@ Stmt::child_range UnaryExprOrTypeTraitExpr::children() { if (const VariableArrayType* T = dyn_cast<VariableArrayType>( getArgumentType().getTypePtr())) return child_range(child_iterator(T), child_iterator()); - return child_range(); + return child_range(child_iterator(), child_iterator()); } return child_range(&Argument.Ex, &Argument.Ex + 1); } -// ObjCMessageExpr -Stmt::child_range ObjCMessageExpr::children() { - Stmt **begin; - if (getReceiverKind() == Instance) - begin = reinterpret_cast<Stmt **>(this + 1); - else - begin = reinterpret_cast<Stmt **>(getArgs()); - return child_range(begin, - reinterpret_cast<Stmt **>(getArgs() + getNumArgs())); -} - -ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr *> Elements, - QualType T, ObjCMethodDecl *Method, - SourceRange SR) - : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary, - false, false, false, false), - NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method) -{ - Expr **SaveElements = getElements(); - for (unsigned I = 0, N = Elements.size(); I != N; ++I) { - if (Elements[I]->isTypeDependent() || Elements[I]->isValueDependent()) - ExprBits.ValueDependent = true; - if (Elements[I]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (Elements[I]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - - SaveElements[I] = Elements[I]; - } -} - -ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C, - ArrayRef<Expr *> Elements, - QualType T, ObjCMethodDecl * Method, - SourceRange SR) { - void *Mem = C.Allocate(sizeof(ObjCArrayLiteral) - + Elements.size() * sizeof(Expr *)); - return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR); -} - -ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C, - unsigned NumElements) { - - void *Mem = C.Allocate(sizeof(ObjCArrayLiteral) - + NumElements * sizeof(Expr *)); - return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements); -} - -ObjCDictionaryLiteral::ObjCDictionaryLiteral( - ArrayRef<ObjCDictionaryElement> VK, - bool HasPackExpansions, - QualType T, ObjCMethodDecl *method, - SourceRange SR) - : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary, false, false, - false, false), - NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR), - DictWithObjectsMethod(method) -{ - KeyValuePair *KeyValues = getKeyValues(); - ExpansionData *Expansions = getExpansionData(); - for (unsigned I = 0; I < NumElements; I++) { - if (VK[I].Key->isTypeDependent() || VK[I].Key->isValueDependent() || - VK[I].Value->isTypeDependent() || VK[I].Value->isValueDependent()) - ExprBits.ValueDependent = true; - if (VK[I].Key->isInstantiationDependent() || - VK[I].Value->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (VK[I].EllipsisLoc.isInvalid() && - (VK[I].Key->containsUnexpandedParameterPack() || - VK[I].Value->containsUnexpandedParameterPack())) - ExprBits.ContainsUnexpandedParameterPack = true; - - KeyValues[I].Key = VK[I].Key; - KeyValues[I].Value = VK[I].Value; - if (Expansions) { - Expansions[I].EllipsisLoc = VK[I].EllipsisLoc; - if (VK[I].NumExpansions) - Expansions[I].NumExpansionsPlusOne = *VK[I].NumExpansions + 1; - else - Expansions[I].NumExpansionsPlusOne = 0; - } - } -} - -ObjCDictionaryLiteral * -ObjCDictionaryLiteral::Create(const ASTContext &C, - ArrayRef<ObjCDictionaryElement> VK, - bool HasPackExpansions, - QualType T, ObjCMethodDecl *method, - SourceRange SR) { - unsigned ExpansionsSize = 0; - if (HasPackExpansions) - ExpansionsSize = sizeof(ExpansionData) * VK.size(); - - void *Mem = C.Allocate(sizeof(ObjCDictionaryLiteral) + - sizeof(KeyValuePair) * VK.size() + ExpansionsSize); - return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR); -} - -ObjCDictionaryLiteral * -ObjCDictionaryLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements, - bool HasPackExpansions) { - unsigned ExpansionsSize = 0; - if (HasPackExpansions) - ExpansionsSize = sizeof(ExpansionData) * NumElements; - void *Mem = C.Allocate(sizeof(ObjCDictionaryLiteral) + - sizeof(KeyValuePair) * NumElements + ExpansionsSize); - return new (Mem) ObjCDictionaryLiteral(EmptyShell(), NumElements, - HasPackExpansions); -} - -ObjCSubscriptRefExpr *ObjCSubscriptRefExpr::Create(const ASTContext &C, - Expr *base, - Expr *key, QualType T, - ObjCMethodDecl *getMethod, - ObjCMethodDecl *setMethod, - SourceLocation RB) { - void *Mem = C.Allocate(sizeof(ObjCSubscriptRefExpr)); - return new (Mem) ObjCSubscriptRefExpr(base, key, T, VK_LValue, - OK_ObjCSubscript, - getMethod, setMethod, RB); -} - AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t, AtomicOp op, SourceLocation RP) : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary, @@ -4373,3 +4009,29 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { } llvm_unreachable("unknown atomic op"); } + +QualType OMPArraySectionExpr::getBaseOriginalType(Expr *Base) { + unsigned ArraySectionCount = 0; + while (auto *OASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParens())) { + Base = OASE->getBase(); + ++ArraySectionCount; + } + while (auto *ASE = dyn_cast<ArraySubscriptExpr>(Base->IgnoreParens())) { + Base = ASE->getBase(); + ++ArraySectionCount; + } + auto OriginalTy = Base->getType(); + if (auto *DRE = dyn_cast<DeclRefExpr>(Base)) + if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) + OriginalTy = PVD->getOriginalType().getNonReferenceType(); + + for (unsigned Cnt = 0; Cnt < ArraySectionCount; ++Cnt) { + if (OriginalTy->isAnyPointerType()) + OriginalTy = OriginalTy->getPointeeType(); + else { + assert (OriginalTy->isArrayType()); + OriginalTy = OriginalTy->castAsArrayTypeUnsafe()->getElementType(); + } + } + return OriginalTy; +} diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index d6f2ce6..ea98334 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -295,8 +295,11 @@ UnresolvedLookupExpr::Create(const ASTContext &C, { assert(Args || TemplateKWLoc.isValid()); unsigned num_args = Args ? Args->size() : 0; - void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + - ASTTemplateKWAndArgsInfo::sizeFor(num_args)); + + std::size_t Size = + totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(1, + num_args); + void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>()); return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, TemplateKWLoc, NameInfo, ADL, /*Overload*/ true, Args, @@ -307,11 +310,11 @@ UnresolvedLookupExpr * UnresolvedLookupExpr::CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { - std::size_t size = sizeof(UnresolvedLookupExpr); - if (HasTemplateKWAndArgsInfo) - size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); - - void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedLookupExpr>()); + assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); + std::size_t Size = + totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( + HasTemplateKWAndArgsInfo, NumTemplateArgs); + void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>()); UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell()); E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; @@ -367,10 +370,9 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, bool Dependent = false; bool InstantiationDependent = false; bool ContainsUnexpandedParameterPack = false; - getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs, - Dependent, - InstantiationDependent, - ContainsUnexpandedParameterPack); + getTrailingASTTemplateKWAndArgsInfo()->initializeFrom( + TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc(), + Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); if (Dependent) { ExprBits.TypeDependent = true; @@ -381,7 +383,7 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C, if (ContainsUnexpandedParameterPack) ExprBits.ContainsUnexpandedParameterPack = true; } else if (TemplateKWLoc.isValid()) { - getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); + getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); } if (isTypeDependent()) @@ -432,13 +434,13 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, bool InstantiationDependent = true; bool ContainsUnexpandedParameterPack = ExprBits.ContainsUnexpandedParameterPack; - getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *Args, - Dependent, - InstantiationDependent, - ContainsUnexpandedParameterPack); + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( + TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>(), + Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; } else if (TemplateKWLoc.isValid()) { - getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( + TemplateKWLoc); } } @@ -449,12 +451,11 @@ DependentScopeDeclRefExpr::Create(const ASTContext &C, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args) { assert(QualifierLoc && "should be created for dependent qualifiers"); - std::size_t size = sizeof(DependentScopeDeclRefExpr); - if (Args) - size += ASTTemplateKWAndArgsInfo::sizeFor(Args->size()); - else if (TemplateKWLoc.isValid()) - size += ASTTemplateKWAndArgsInfo::sizeFor(0); - void *Mem = C.Allocate(size); + bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid(); + std::size_t Size = + totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( + HasTemplateKWAndArgsInfo, Args ? Args->size() : 0); + void *Mem = C.Allocate(Size); return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc, TemplateKWLoc, NameInfo, Args); } @@ -463,10 +464,11 @@ DependentScopeDeclRefExpr * DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { - std::size_t size = sizeof(DependentScopeDeclRefExpr); - if (HasTemplateKWAndArgsInfo) - size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); - void *Mem = C.Allocate(size); + assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); + std::size_t Size = + totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( + HasTemplateKWAndArgsInfo, NumTemplateArgs); + void *Mem = C.Allocate(Size); DependentScopeDeclRefExpr *E = new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(), SourceLocation(), @@ -587,19 +589,19 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T, SourceLocation RParenLoc, SourceRange AngleBrackets) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = C.Allocate(sizeof(CXXStaticCastExpr) - + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); CXXStaticCastExpr *E = new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, RParenLoc, AngleBrackets); - if (PathSize) E->setCastPath(*BasePath); + if (PathSize) + std::uninitialized_copy_n(BasePath->data(), BasePath->size(), + E->getTrailingObjects<CXXBaseSpecifier *>()); return E; } CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = - C.Allocate(sizeof(CXXStaticCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize); } @@ -612,19 +614,19 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T, SourceLocation RParenLoc, SourceRange AngleBrackets) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = C.Allocate(sizeof(CXXDynamicCastExpr) - + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); CXXDynamicCastExpr *E = new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, RParenLoc, AngleBrackets); - if (PathSize) E->setCastPath(*BasePath); + if (PathSize) + std::uninitialized_copy_n(BasePath->data(), BasePath->size(), + E->getTrailingObjects<CXXBaseSpecifier *>()); return E; } CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = - C.Allocate(sizeof(CXXDynamicCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize); } @@ -669,19 +671,19 @@ CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T, SourceLocation RParenLoc, SourceRange AngleBrackets) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = - C.Allocate(sizeof(CXXReinterpretCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); CXXReinterpretCastExpr *E = new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, RParenLoc, AngleBrackets); - if (PathSize) E->setCastPath(*BasePath); + if (PathSize) + std::uninitialized_copy_n(BasePath->data(), BasePath->size(), + E->getTrailingObjects<CXXBaseSpecifier *>()); return E; } CXXReinterpretCastExpr * CXXReinterpretCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = C.Allocate(sizeof(CXXReinterpretCastExpr) - + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize); } @@ -704,18 +706,18 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, const CXXCastPath *BasePath, SourceLocation L, SourceLocation R) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr) - + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); CXXFunctionalCastExpr *E = new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R); - if (PathSize) E->setCastPath(*BasePath); + if (PathSize) + std::uninitialized_copy_n(BasePath->data(), BasePath->size(), + E->getTrailingObjects<CXXBaseSpecifier *>()); return E; } CXXFunctionalCastExpr * CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr) - + PathSize * sizeof(CXXBaseSpecifier*)); + void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize)); return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize); } @@ -761,14 +763,6 @@ const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const { return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier(); } -CXXDefaultArgExpr * -CXXDefaultArgExpr::Create(const ASTContext &C, SourceLocation Loc, - ParmVarDecl *Param, Expr *SubExpr) { - void *Mem = C.Allocate(sizeof(CXXDefaultArgExpr) + sizeof(Stmt *)); - return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, - SubExpr); -} - CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field, QualType T) : Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C), @@ -922,29 +916,22 @@ LambdaCaptureKind LambdaCapture::getCaptureKind() const { return CapByCopy ? LCK_ByCopy : LCK_ByRef; } -LambdaExpr::LambdaExpr(QualType T, - SourceRange IntroducerRange, +LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, - ArrayRef<Capture> Captures, - bool ExplicitParams, - bool ExplicitResultType, - ArrayRef<Expr *> CaptureInits, + ArrayRef<LambdaCapture> Captures, bool ExplicitParams, + bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) - : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, - T->isDependentType(), T->isDependentType(), T->isDependentType(), - ContainsUnexpandedParameterPack), - IntroducerRange(IntroducerRange), - CaptureDefaultLoc(CaptureDefaultLoc), - NumCaptures(Captures.size()), - CaptureDefault(CaptureDefault), - ExplicitParams(ExplicitParams), - ExplicitResultType(ExplicitResultType), - ClosingBrace(ClosingBrace) -{ + : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(), + T->isDependentType(), T->isDependentType(), + ContainsUnexpandedParameterPack), + IntroducerRange(IntroducerRange), CaptureDefaultLoc(CaptureDefaultLoc), + NumCaptures(Captures.size()), CaptureDefault(CaptureDefault), + ExplicitParams(ExplicitParams), ExplicitResultType(ExplicitResultType), + ClosingBrace(ClosingBrace) { assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments"); CXXRecordDecl *Class = getLambdaClass(); CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData(); @@ -955,8 +942,9 @@ LambdaExpr::LambdaExpr(QualType T, const ASTContext &Context = Class->getASTContext(); Data.NumCaptures = NumCaptures; Data.NumExplicitCaptures = 0; - Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures); - Capture *ToCapture = Data.Captures; + Data.Captures = + (LambdaCapture *)Context.Allocate(sizeof(LambdaCapture) * NumCaptures); + LambdaCapture *ToCapture = Data.Captures; for (unsigned I = 0, N = Captures.size(); I != N; ++I) { if (Captures[I].isExplicit()) ++Data.NumExplicitCaptures; @@ -984,30 +972,20 @@ LambdaExpr::LambdaExpr(QualType T, } } -LambdaExpr *LambdaExpr::Create(const ASTContext &Context, - CXXRecordDecl *Class, - SourceRange IntroducerRange, - LambdaCaptureDefault CaptureDefault, - SourceLocation CaptureDefaultLoc, - ArrayRef<Capture> Captures, - bool ExplicitParams, - bool ExplicitResultType, - ArrayRef<Expr *> CaptureInits, - ArrayRef<VarDecl *> ArrayIndexVars, - ArrayRef<unsigned> ArrayIndexStarts, - SourceLocation ClosingBrace, - bool ContainsUnexpandedParameterPack) { +LambdaExpr *LambdaExpr::Create( + const ASTContext &Context, CXXRecordDecl *Class, + SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, + SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, + bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, + ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts, + SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) { // Determine the type of the expression (i.e., the type of the // function object we're creating). QualType T = Context.getTypeDeclType(Class); - unsigned Size = sizeof(LambdaExpr) + sizeof(Stmt *) * (Captures.size() + 1); - if (!ArrayIndexVars.empty()) { - Size += sizeof(unsigned) * (Captures.size() + 1); - // Realign for following VarDecl array. - Size = llvm::RoundUpToAlignment(Size, llvm::alignOf<VarDecl*>()); - Size += sizeof(VarDecl *) * ArrayIndexVars.size(); - } + unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>( + Captures.size() + 1, ArrayIndexVars.empty() ? 0 : Captures.size() + 1, + ArrayIndexVars.size()); void *Mem = Context.Allocate(Size); return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc, Captures, @@ -1019,10 +997,9 @@ LambdaExpr *LambdaExpr::Create(const ASTContext &Context, LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C, unsigned NumCaptures, unsigned NumArrayIndexVars) { - unsigned Size = sizeof(LambdaExpr) + sizeof(Stmt *) * (NumCaptures + 1); - if (NumArrayIndexVars) - Size += sizeof(VarDecl) * NumArrayIndexVars - + sizeof(unsigned) * (NumCaptures + 1); + unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>( + NumCaptures + 1, NumArrayIndexVars ? NumCaptures + 1 : 0, + NumArrayIndexVars); void *Mem = C.Allocate(Size); return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0); } @@ -1070,15 +1047,15 @@ 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 { +ArrayRef<VarDecl *> +LambdaExpr::getCaptureInitIndexVars(const_capture_init_iterator Iter) const { assert(HasArrayIndexVars && "No array index-var data?"); unsigned Index = Iter - capture_init_begin(); assert(Index < getLambdaClass()->getLambdaData().NumCaptures && "Capture index out-of-range"); - VarDecl **IndexVars = getArrayIndexVars(); - unsigned *IndexStarts = getArrayIndexStarts(); + VarDecl *const *IndexVars = getArrayIndexVars(); + const unsigned *IndexStarts = getArrayIndexStarts(); return llvm::makeArrayRef(IndexVars + IndexStarts[Index], IndexVars + IndexStarts[Index + 1]); } @@ -1099,10 +1076,14 @@ TemplateParameterList *LambdaExpr::getTemplateParameterList() const { } CompoundStmt *LambdaExpr::getBody() const { + // FIXME: this mutation in getBody is bogus. It should be + // initialized in ASTStmtReader::VisitLambdaExpr, but for reasons I + // don't understand, that doesn't work. if (!getStoredStmts()[NumCaptures]) - getStoredStmts()[NumCaptures] = getCallOperator()->getBody(); - - return reinterpret_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]); + *const_cast<clang::Stmt **>(&getStoredStmts()[NumCaptures]) = + getCallOperator()->getBody(); + + return static_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]); } bool LambdaExpr::isMutable() const { @@ -1119,14 +1100,13 @@ ExprWithCleanups::ExprWithCleanups(Expr *subexpr, SubExpr(subexpr) { ExprWithCleanupsBits.NumObjects = objects.size(); for (unsigned i = 0, e = objects.size(); i != e; ++i) - getObjectsBuffer()[i] = objects[i]; + getTrailingObjects<CleanupObject>()[i] = objects[i]; } ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr, ArrayRef<CleanupObject> objects) { - size_t size = sizeof(ExprWithCleanups) - + objects.size() * sizeof(CleanupObject); - void *buffer = C.Allocate(size, llvm::alignOf<ExprWithCleanups>()); + void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()), + llvm::alignOf<ExprWithCleanups>()); return new (buffer) ExprWithCleanups(subexpr, objects); } @@ -1138,8 +1118,8 @@ ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects) ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, EmptyShell empty, unsigned numObjects) { - size_t size = sizeof(ExprWithCleanups) + numObjects * sizeof(CleanupObject); - void *buffer = C.Allocate(size, llvm::alignOf<ExprWithCleanups>()); + void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(numObjects), + llvm::alignOf<ExprWithCleanups>()); return new (buffer) ExprWithCleanups(empty, numObjects); } @@ -1159,7 +1139,7 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type, LParenLoc(LParenLoc), RParenLoc(RParenLoc), NumArgs(Args.size()) { - Stmt **StoredArgs = reinterpret_cast<Stmt **>(this + 1); + Expr **StoredArgs = getTrailingObjects<Expr *>(); for (unsigned I = 0; I != Args.size(); ++I) { if (Args[I]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; @@ -1174,16 +1154,14 @@ CXXUnresolvedConstructExpr::Create(const ASTContext &C, SourceLocation LParenLoc, ArrayRef<Expr*> Args, SourceLocation RParenLoc) { - void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) + - sizeof(Expr *) * Args.size()); + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Args.size())); return new (Mem) CXXUnresolvedConstructExpr(Type, LParenLoc, Args, RParenLoc); } CXXUnresolvedConstructExpr * CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &C, unsigned NumArgs) { Stmt::EmptyShell Empty; - void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) + - sizeof(Expr *) * NumArgs); + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumArgs)); return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs); } @@ -1191,63 +1169,40 @@ SourceLocation CXXUnresolvedConstructExpr::getLocStart() const { return Type->getTypeLoc().getBeginLoc(); } -CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(const ASTContext &C, - Expr *Base, QualType BaseType, - bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierFoundInScope, - DeclarationNameInfo MemberNameInfo, - const TemplateArgumentListInfo *TemplateArgs) - : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, - VK_LValue, OK_Ordinary, true, true, true, - ((Base && Base->containsUnexpandedParameterPack()) || - (QualifierLoc && - QualifierLoc.getNestedNameSpecifier() - ->containsUnexpandedParameterPack()) || - MemberNameInfo.containsUnexpandedParameterPack())), - Base(Base), BaseType(BaseType), IsArrow(IsArrow), - HasTemplateKWAndArgsInfo(TemplateArgs != nullptr || - TemplateKWLoc.isValid()), - OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), - FirstQualifierFoundInScope(FirstQualifierFoundInScope), - MemberNameInfo(MemberNameInfo) { +CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( + const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, + DeclarationNameInfo MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs) + : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, VK_LValue, + OK_Ordinary, true, true, true, + ((Base && Base->containsUnexpandedParameterPack()) || + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()) || + MemberNameInfo.containsUnexpandedParameterPack())), + Base(Base), BaseType(BaseType), IsArrow(IsArrow), + HasTemplateKWAndArgsInfo(TemplateArgs != nullptr || + TemplateKWLoc.isValid()), + OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), + FirstQualifierFoundInScope(FirstQualifierFoundInScope), + MemberNameInfo(MemberNameInfo) { if (TemplateArgs) { bool Dependent = true; bool InstantiationDependent = true; bool ContainsUnexpandedParameterPack = false; - getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs, - Dependent, - InstantiationDependent, - ContainsUnexpandedParameterPack); + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( + TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(), + Dependent, InstantiationDependent, ContainsUnexpandedParameterPack); if (ContainsUnexpandedParameterPack) ExprBits.ContainsUnexpandedParameterPack = true; } else if (TemplateKWLoc.isValid()) { - getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( + TemplateKWLoc); } } -CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(const ASTContext &C, - Expr *Base, QualType BaseType, - bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - NamedDecl *FirstQualifierFoundInScope, - DeclarationNameInfo MemberNameInfo) - : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, - VK_LValue, OK_Ordinary, true, true, true, - ((Base && Base->containsUnexpandedParameterPack()) || - (QualifierLoc && - QualifierLoc.getNestedNameSpecifier()-> - containsUnexpandedParameterPack()) || - MemberNameInfo.containsUnexpandedParameterPack())), - Base(Base), BaseType(BaseType), IsArrow(IsArrow), - HasTemplateKWAndArgsInfo(false), - OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), - FirstQualifierFoundInScope(FirstQualifierFoundInScope), - MemberNameInfo(MemberNameInfo) { } - CXXDependentScopeMemberExpr * CXXDependentScopeMemberExpr::Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, @@ -1257,18 +1212,13 @@ CXXDependentScopeMemberExpr::Create(const ASTContext &C, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) { - if (!TemplateArgs && !TemplateKWLoc.isValid()) - return new (C) CXXDependentScopeMemberExpr(C, Base, BaseType, - IsArrow, OperatorLoc, - QualifierLoc, - FirstQualifierFoundInScope, - MemberNameInfo); - + bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0; - std::size_t size = sizeof(CXXDependentScopeMemberExpr) - + ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); + std::size_t Size = + totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( + HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>()); + void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>()); return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, @@ -1281,22 +1231,18 @@ CXXDependentScopeMemberExpr * CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { - if (!HasTemplateKWAndArgsInfo) - return new (C) CXXDependentScopeMemberExpr(C, nullptr, QualType(), - 0, SourceLocation(), - NestedNameSpecifierLoc(), - nullptr, DeclarationNameInfo()); - - std::size_t size = sizeof(CXXDependentScopeMemberExpr) + - ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); - void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>()); + assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); + std::size_t Size = + totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( + HasTemplateKWAndArgsInfo, NumTemplateArgs); + void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>()); CXXDependentScopeMemberExpr *E = new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(), 0, SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), nullptr, DeclarationNameInfo(), nullptr); - E->HasTemplateKWAndArgsInfo = true; + E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; } @@ -1361,38 +1307,34 @@ bool UnresolvedMemberExpr::isImplicitAccess() const { return cast<Expr>(Base)->isImplicitCXXThis(); } -UnresolvedMemberExpr * -UnresolvedMemberExpr::Create(const ASTContext &C, bool HasUnresolvedUsing, - Expr *Base, QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &MemberNameInfo, - const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { - std::size_t size = sizeof(UnresolvedMemberExpr); - if (TemplateArgs) - size += ASTTemplateKWAndArgsInfo::sizeFor(TemplateArgs->size()); - else if (TemplateKWLoc.isValid()) - size += ASTTemplateKWAndArgsInfo::sizeFor(0); - - void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>()); - return new (Mem) UnresolvedMemberExpr(C, - HasUnresolvedUsing, Base, BaseType, - IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc, - MemberNameInfo, TemplateArgs, Begin, End); +UnresolvedMemberExpr *UnresolvedMemberExpr::Create( + const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, + bool IsArrow, SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { + bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); + std::size_t Size = + totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( + HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0); + + void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>()); + return new (Mem) UnresolvedMemberExpr( + C, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, + TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End); } UnresolvedMemberExpr * UnresolvedMemberExpr::CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { - std::size_t size = sizeof(UnresolvedMemberExpr); - if (HasTemplateKWAndArgsInfo) - size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); + assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo); + std::size_t Size = + totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>( + HasTemplateKWAndArgsInfo, NumTemplateArgs); - void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>()); + void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>()); UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell()); E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; @@ -1428,6 +1370,25 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { return Record; } +SizeOfPackExpr * +SizeOfPackExpr::Create(ASTContext &Context, SourceLocation OperatorLoc, + NamedDecl *Pack, SourceLocation PackLoc, + SourceLocation RParenLoc, + Optional<unsigned> Length, + ArrayRef<TemplateArgument> PartialArgs) { + void *Storage = + Context.Allocate(totalSizeToAlloc<TemplateArgument>(PartialArgs.size())); + return new (Storage) SizeOfPackExpr(Context.getSizeType(), OperatorLoc, Pack, + PackLoc, RParenLoc, Length, PartialArgs); +} + +SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context, + unsigned NumPartialArgs) { + void *Storage = + Context.Allocate(totalSizeToAlloc<TemplateArgument>(NumPartialArgs)); + return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs); +} + SubstNonTypeTemplateParmPackExpr:: SubstNonTypeTemplateParmPackExpr(QualType T, NonTypeTemplateParmDecl *Param, @@ -1439,36 +1400,34 @@ SubstNonTypeTemplateParmPackExpr(QualType T, NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { } TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const { - return TemplateArgument(Arguments, NumArguments); + return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments)); } FunctionParmPackExpr::FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack, SourceLocation NameLoc, unsigned NumParams, - Decl * const *Params) - : Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary, - true, true, true, true), - ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) { + ParmVarDecl *const *Params) + : Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary, true, true, + true, true), + ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) { if (Params) std::uninitialized_copy(Params, Params + NumParams, - reinterpret_cast<Decl**>(this+1)); + getTrailingObjects<ParmVarDecl *>()); } FunctionParmPackExpr * FunctionParmPackExpr::Create(const ASTContext &Context, QualType T, ParmVarDecl *ParamPack, SourceLocation NameLoc, - ArrayRef<Decl *> Params) { - return new (Context.Allocate(sizeof(FunctionParmPackExpr) + - sizeof(ParmVarDecl*) * Params.size())) - FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data()); + ArrayRef<ParmVarDecl *> Params) { + return new (Context.Allocate(totalSizeToAlloc<ParmVarDecl *>(Params.size()))) + FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data()); } FunctionParmPackExpr * FunctionParmPackExpr::CreateEmpty(const ASTContext &Context, unsigned NumParams) { - return new (Context.Allocate(sizeof(FunctionParmPackExpr) + - sizeof(ParmVarDecl*) * NumParams)) - FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr); + return new (Context.Allocate(totalSizeToAlloc<ParmVarDecl *>(NumParams))) + FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr); } void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy, @@ -1505,8 +1464,8 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, TypeTraitExprBits.Value = Value; TypeTraitExprBits.NumArgs = Args.size(); - TypeSourceInfo **ToArgs = getTypeSourceInfos(); - + TypeSourceInfo **ToArgs = getTrailingObjects<TypeSourceInfo *>(); + for (unsigned I = 0, N = Args.size(); I != N; ++I) { if (Args[I]->getType()->isDependentType()) setValueDependent(true); @@ -1525,15 +1484,13 @@ TypeTraitExpr *TypeTraitExpr::Create(const ASTContext &C, QualType T, ArrayRef<TypeSourceInfo *> Args, SourceLocation RParenLoc, bool Value) { - unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * Args.size(); - void *Mem = C.Allocate(Size); + void *Mem = C.Allocate(totalSizeToAlloc<TypeSourceInfo *>(Args.size())); return new (Mem) TypeTraitExpr(T, Loc, Kind, Args, RParenLoc, Value); } TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C, unsigned NumArgs) { - unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * NumArgs; - void *Mem = C.Allocate(Size); + void *Mem = C.Allocate(totalSizeToAlloc<TypeSourceInfo *>(NumArgs)); return new (Mem) TypeTraitExpr(EmptyShell()); } diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index 9cc612e..a47b03c 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -136,6 +136,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ObjCIvarRefExprClass: case Expr::FunctionParmPackExprClass: case Expr::MSPropertyRefExprClass: + case Expr::MSPropertySubscriptExprClass: + case Expr::OMPArraySectionExprClass: return Cl::CL_LValue; // C99 6.5.2.5p5 says that compound literals are lvalues. @@ -185,6 +187,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CXXFoldExprClass: case Expr::NoInitExprClass: case Expr::DesignatedInitUpdateExprClass: + case Expr::CoyieldExprClass: return Cl::CL_PRValue; // Next come the complicated cases. @@ -396,6 +399,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { assert(cast<InitListExpr>(E)->getNumInits() == 1 && "Only 1-element init lists can be glvalues."); return ClassifyInternal(Ctx, cast<InitListExpr>(E)->getInit(0)); + + case Expr::CoawaitExprClass: + return ClassifyInternal(Ctx, cast<CoawaitExpr>(E)->getResumeExpr()); } llvm_unreachable("unhandled expression kind in classification"); diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index ed749cc..fa652ba 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -114,7 +114,8 @@ namespace { static unsigned findMostDerivedSubobject(ASTContext &Ctx, QualType Base, ArrayRef<APValue::LValuePathEntry> Path, - uint64_t &ArraySize, QualType &Type) { + uint64_t &ArraySize, QualType &Type, + bool &IsArray) { unsigned MostDerivedLength = 0; Type = Base; for (unsigned I = 0, N = Path.size(); I != N; ++I) { @@ -124,18 +125,22 @@ namespace { Type = CAT->getElementType(); ArraySize = CAT->getSize().getZExtValue(); MostDerivedLength = I + 1; + IsArray = true; } else if (Type->isAnyComplexType()) { const ComplexType *CT = Type->castAs<ComplexType>(); Type = CT->getElementType(); ArraySize = 2; MostDerivedLength = I + 1; + IsArray = true; } else if (const FieldDecl *FD = getAsField(Path[I])) { Type = FD->getType(); ArraySize = 0; MostDerivedLength = I + 1; + IsArray = false; } else { // Path[I] describes a base class. ArraySize = 0; + IsArray = false; } } return MostDerivedLength; @@ -157,12 +162,17 @@ namespace { /// Is this a pointer one past the end of an object? bool IsOnePastTheEnd : 1; + /// Indicator of whether the most-derived object is an array element. + bool MostDerivedIsArrayElement : 1; + /// The length of the path to the most-derived object of which this is a /// subobject. - unsigned MostDerivedPathLength : 30; + unsigned MostDerivedPathLength : 29; - /// The size of the array of which the most-derived object is an element, or - /// 0 if the most-derived object is not an array element. + /// The size of the array of which the most-derived object is an element. + /// This will always be 0 if the most-derived object is not an array + /// element. 0 is not an indicator of whether or not the most-derived object + /// is an array, however, because 0-length arrays are allowed. uint64_t MostDerivedArraySize; /// The type of the most derived object referred to by this address. @@ -176,21 +186,26 @@ namespace { SubobjectDesignator() : Invalid(true) {} explicit SubobjectDesignator(QualType T) - : Invalid(false), IsOnePastTheEnd(false), MostDerivedPathLength(0), - MostDerivedArraySize(0), MostDerivedType(T) {} + : Invalid(false), IsOnePastTheEnd(false), + MostDerivedIsArrayElement(false), MostDerivedPathLength(0), + MostDerivedArraySize(0), MostDerivedType(T) {} SubobjectDesignator(ASTContext &Ctx, const APValue &V) - : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false), - MostDerivedPathLength(0), MostDerivedArraySize(0) { + : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false), + MostDerivedIsArrayElement(false), MostDerivedPathLength(0), + MostDerivedArraySize(0) { if (!Invalid) { IsOnePastTheEnd = V.isLValueOnePastTheEnd(); ArrayRef<PathEntry> VEntries = V.getLValuePath(); Entries.insert(Entries.end(), VEntries.begin(), VEntries.end()); - if (V.getLValueBase()) + if (V.getLValueBase()) { + bool IsArray = false; MostDerivedPathLength = findMostDerivedSubobject(Ctx, getType(V.getLValueBase()), V.getLValuePath(), MostDerivedArraySize, - MostDerivedType); + MostDerivedType, IsArray); + MostDerivedIsArrayElement = IsArray; + } } } @@ -204,7 +219,7 @@ namespace { assert(!Invalid); if (IsOnePastTheEnd) return true; - if (MostDerivedArraySize && + if (MostDerivedIsArrayElement && Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize) return true; return false; @@ -228,6 +243,7 @@ namespace { // This is a most-derived object. MostDerivedType = CAT->getElementType(); + MostDerivedIsArrayElement = true; MostDerivedArraySize = CAT->getSize().getZExtValue(); MostDerivedPathLength = Entries.size(); } @@ -242,6 +258,7 @@ namespace { // If this isn't a base class, it's a new most-derived object. if (const FieldDecl *FD = dyn_cast<FieldDecl>(D)) { MostDerivedType = FD->getType(); + MostDerivedIsArrayElement = false; MostDerivedArraySize = 0; MostDerivedPathLength = Entries.size(); } @@ -255,6 +272,7 @@ namespace { // This is technically a most-derived object, though in practice this // is unlikely to matter. MostDerivedType = EltTy; + MostDerivedIsArrayElement = true; MostDerivedArraySize = 2; MostDerivedPathLength = Entries.size(); } @@ -262,7 +280,8 @@ namespace { /// Add N to the address of this subobject. void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { if (Invalid) return; - if (MostDerivedPathLength == Entries.size() && MostDerivedArraySize) { + if (MostDerivedPathLength == Entries.size() && + MostDerivedIsArrayElement) { Entries.back().ArrayIndex += N; if (Entries.back().ArrayIndex > MostDerivedArraySize) { diagnosePointerArithmetic(Info, E, Entries.back().ArrayIndex); @@ -454,6 +473,10 @@ namespace { /// notes attached to it will also be stored, otherwise they will not be. bool HasActiveDiagnostic; + /// \brief Have we emitted a diagnostic explaining why we couldn't constant + /// fold (not just why it's not strictly a constant expression)? + bool HasFoldFailureDiagnostic; + enum EvaluationMode { /// Evaluate as a constant expression. Stop if we find that the expression /// is not a constant expression. @@ -492,7 +515,11 @@ namespace { /// 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 + EM_PotentialConstantExpressionUnevaluated, + + /// Evaluate as a constant expression. Continue evaluating if we find a + /// MemberExpr with a base that can't be evaluated. + EM_DesignatorFold, } EvalMode; /// Are we checking whether the expression is a potential constant @@ -514,7 +541,7 @@ namespace { BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr), EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), - EvalMode(Mode) {} + HasFoldFailureDiagnostic(false), EvalMode(Mode) {} void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; @@ -574,7 +601,7 @@ namespace { /// Diagnose that the evaluation cannot be folded. OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, - unsigned ExtraNotes = 0) { + unsigned ExtraNotes = 0, bool IsCCEDiag = false) { if (EvalStatus.Diag) { // If we have a prior diagnostic, it will be noting that the expression // isn't a constant expression. This diagnostic is more important, @@ -587,14 +614,14 @@ namespace { case EM_ConstantFold: case EM_IgnoreSideEffects: case EM_EvaluateForOverflow: - if (!EvalStatus.HasSideEffects) + if (!HasFoldFailureDiagnostic) break; - // We've had side-effects; we want the diagnostic from them, not - // some later problem. + // We've already failed to fold something. Keep that diagnostic. case EM_ConstantExpression: case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_PotentialConstantExpressionUnevaluated: + case EM_DesignatorFold: HasActiveDiagnostic = false; return OptionalDiagnostic(); } @@ -608,6 +635,7 @@ namespace { CallStackNotes = 0; HasActiveDiagnostic = true; + HasFoldFailureDiagnostic = !IsCCEDiag; EvalStatus.Diag->clear(); EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes); addDiag(Loc, DiagId); @@ -621,9 +649,9 @@ namespace { OptionalDiagnostic Diag(const Expr *E, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, - unsigned ExtraNotes = 0) { + unsigned ExtraNotes = 0, bool IsCCEDiag = false) { if (EvalStatus.Diag) - return Diag(E->getExprLoc(), DiagId, ExtraNotes); + return Diag(E->getExprLoc(), DiagId, ExtraNotes, IsCCEDiag); HasActiveDiagnostic = false; return OptionalDiagnostic(); } @@ -643,7 +671,7 @@ namespace { HasActiveDiagnostic = false; return OptionalDiagnostic(); } - return Diag(Loc, DiagId, ExtraNotes); + return Diag(Loc, DiagId, ExtraNotes, true); } /// Add a note to a prior diagnostic. @@ -674,6 +702,7 @@ namespace { case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: + case EM_DesignatorFold: return false; } llvm_unreachable("Missed EvalMode case"); @@ -686,6 +715,32 @@ namespace { return keepEvaluatingAfterSideEffect(); } + /// Should we continue evaluation after encountering undefined behavior? + bool keepEvaluatingAfterUndefinedBehavior() { + switch (EvalMode) { + case EM_EvaluateForOverflow: + case EM_IgnoreSideEffects: + case EM_ConstantFold: + case EM_DesignatorFold: + return true; + + case EM_PotentialConstantExpression: + case EM_PotentialConstantExpressionUnevaluated: + case EM_ConstantExpression: + case EM_ConstantExpressionUnevaluated: + return false; + } + llvm_unreachable("Missed EvalMode case"); + } + + /// Note that we hit something that was technically undefined behavior, but + /// that we can evaluate past it (such as signed overflow or floating-point + /// division by zero.) + bool noteUndefinedBehavior() { + EvalStatus.HasUndefinedBehavior = true; + return keepEvaluatingAfterUndefinedBehavior(); + } + /// Should we continue evaluation as much as possible after encountering a /// construct which can't be reduced to a value? bool keepEvaluatingAfterFailure() { @@ -702,10 +757,15 @@ namespace { case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_IgnoreSideEffects: + case EM_DesignatorFold: return false; } llvm_unreachable("Missed EvalMode case"); } + + bool allowInvalidBaseExpr() const { + return EvalMode == EM_DesignatorFold; + } }; /// Object used to treat all foldable expressions as constant expressions. @@ -736,6 +796,21 @@ namespace { } }; + /// RAII object used to treat the current evaluation as the correct pointer + /// offset fold for the current EvalMode + struct FoldOffsetRAII { + EvalInfo &Info; + EvalInfo::EvaluationMode OldMode; + explicit FoldOffsetRAII(EvalInfo &Info, bool Subobject) + : Info(Info), OldMode(Info.EvalMode) { + if (!Info.checkingPotentialConstantExpression()) + Info.EvalMode = Subobject ? EvalInfo::EM_DesignatorFold + : EvalInfo::EM_ConstantFold; + } + + ~FoldOffsetRAII() { Info.EvalMode = OldMode; } + }; + /// RAII object used to suppress diagnostics and side-effects from a /// speculative evaluation. class SpeculativeEvaluationRAII { @@ -808,7 +883,7 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, uint64_t N) { - if (MostDerivedPathLength == Entries.size() && MostDerivedArraySize) + if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement) Info.CCEDiag(E, diag::note_constexpr_array_index) << static_cast<int>(N) << /*array*/ 0 << static_cast<unsigned>(MostDerivedArraySize); @@ -917,7 +992,8 @@ namespace { struct LValue { APValue::LValueBase Base; CharUnits Offset; - unsigned CallIndex; + bool InvalidBase : 1; + unsigned CallIndex : 31; SubobjectDesignator Designator; const APValue::LValueBase getLValueBase() const { return Base; } @@ -938,17 +1014,23 @@ namespace { assert(V.isLValue()); Base = V.getLValueBase(); Offset = V.getLValueOffset(); + InvalidBase = false; CallIndex = V.getLValueCallIndex(); Designator = SubobjectDesignator(Ctx, V); } - void set(APValue::LValueBase B, unsigned I = 0) { + void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) { Base = B; Offset = CharUnits::Zero(); + InvalidBase = BInvalid; CallIndex = I; Designator = SubobjectDesignator(getType(B)); } + void setInvalid(APValue::LValueBase B, unsigned I = 0) { + set(B, I, true); + } + // Check that this LValue is not based on a null pointer. If it is, produce // a diagnostic and mark the designator as invalid. bool checkNullPointer(EvalInfo &Info, const Expr *E, @@ -967,10 +1049,6 @@ namespace { // Check this LValue refers to an object. If not, set the designator to be // invalid and emit a diagnostic. bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { - // Outside C++11, do not build a designator referring to a subobject of - // any object: we won't use such a designator for anything. - if (!Info.getLangOpts().CPlusPlus11) - Designator.setInvalid(); return (CSK == CSK_ArrayToPointer || checkNullPointer(Info, E, CSK)) && Designator.checkSubobject(Info, E, CSK); } @@ -1102,12 +1180,13 @@ static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, EvalInfo &Info); static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info); -static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); +static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info); static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info); static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info); +static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result); //===----------------------------------------------------------------------===// // Misc utilities @@ -1492,10 +1571,11 @@ static bool EvaluateAsBooleanCondition(const Expr *E, bool &Result, } template<typename T> -static void HandleOverflow(EvalInfo &Info, const Expr *E, +static bool HandleOverflow(EvalInfo &Info, const Expr *E, const T &SrcValue, QualType DestType) { Info.CCEDiag(E, diag::note_constexpr_overflow) << SrcValue << DestType; + return Info.noteUndefinedBehavior(); } static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E, @@ -1509,7 +1589,7 @@ static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E, bool ignored; if (Value.convertToInteger(Result, llvm::APFloat::rmTowardZero, &ignored) & APFloat::opInvalidOp) - HandleOverflow(Info, E, Value, DestType); + return HandleOverflow(Info, E, Value, DestType); return true; } @@ -1521,13 +1601,13 @@ static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E, if (Result.convert(Info.Ctx.getFloatTypeSemantics(DestType), APFloat::rmNearestTiesToEven, &ignored) & APFloat::opOverflow) - HandleOverflow(Info, E, Value, DestType); + return HandleOverflow(Info, E, Value, DestType); return true; } static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E, QualType DestType, QualType SrcType, - APSInt &Value) { + const APSInt &Value) { unsigned DestWidth = Info.Ctx.getIntWidth(DestType); APSInt Result = Value; // Figure out if this is a truncate, extend or noop cast. @@ -1544,7 +1624,7 @@ static bool HandleIntToFloatCast(EvalInfo &Info, const Expr *E, if (Result.convertFromAPInt(Value, Value.isSigned(), APFloat::rmNearestTiesToEven) & APFloat::opOverflow) - HandleOverflow(Info, E, Value, DestType); + return HandleOverflow(Info, E, Value, DestType); return true; } @@ -1620,23 +1700,26 @@ static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E, /// bits, and check for overflow in the original type (if that type was not an /// unsigned type). template<typename Operation> -static APSInt CheckedIntArithmetic(EvalInfo &Info, const Expr *E, - const APSInt &LHS, const APSInt &RHS, - unsigned BitWidth, Operation Op) { - if (LHS.isUnsigned()) - return Op(LHS, RHS); +static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E, + const APSInt &LHS, const APSInt &RHS, + unsigned BitWidth, Operation Op, + APSInt &Result) { + if (LHS.isUnsigned()) { + Result = Op(LHS, RHS); + return true; + } APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false); - APSInt Result = Value.trunc(LHS.getBitWidth()); + Result = Value.trunc(LHS.getBitWidth()); if (Result.extend(BitWidth) != Value) { if (Info.checkingForOverflow()) Info.Ctx.getDiagnostics().Report(E->getExprLoc(), - diag::warn_integer_constant_overflow) + diag::warn_integer_constant_overflow) << Result.toString(10) << E->getType(); else - HandleOverflow(Info, E, Value, E->getType()); + return HandleOverflow(Info, E, Value, E->getType()); } - return Result; + return true; } /// Perform the given binary integer operation. @@ -1648,17 +1731,14 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, Info.Diag(E); return false; case BO_Mul: - Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2, - std::multiplies<APSInt>()); - return true; + return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2, + std::multiplies<APSInt>(), Result); case BO_Add: - Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, - std::plus<APSInt>()); - return true; + return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, + std::plus<APSInt>(), Result); case BO_Sub: - Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, - std::minus<APSInt>()); - return true; + return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, + std::minus<APSInt>(), Result); case BO_And: Result = LHS & RHS; return true; case BO_Xor: Result = LHS ^ RHS; return true; case BO_Or: Result = LHS | RHS; return true; @@ -1668,11 +1748,13 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, Info.Diag(E, diag::note_expr_divide_by_zero); return false; } - // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. + Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS); + // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. APSInt supports + // this operation and gives the two's complement result. if (RHS.isNegative() && RHS.isAllOnesValue() && LHS.isSigned() && LHS.isMinSignedValue()) - HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), E->getType()); - Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS); + return HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), + E->getType()); return true; case BO_Shl: { if (Info.getLangOpts().OpenCL) @@ -1760,8 +1842,10 @@ static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E, break; } - if (LHS.isInfinity() || LHS.isNaN()) + if (LHS.isInfinity() || LHS.isNaN()) { Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); + return Info.noteUndefinedBehavior(); + } return true; } @@ -2159,6 +2243,7 @@ enum AccessKinds { AK_Decrement }; +namespace { /// A handle to a complete object (an object that is not a subobject of /// another object). struct CompleteObject { @@ -2175,6 +2260,7 @@ struct CompleteObject { explicit operator bool() const { return Value; } }; +} // end anonymous namespace /// Find the designated sub-object of an rvalue. template<typename SubobjectHandler> @@ -2488,7 +2574,7 @@ static bool AreElementsOfSameArray(QualType ObjType, if (A.Entries.size() != B.Entries.size()) return false; - bool IsArray = A.MostDerivedArraySize != 0; + bool IsArray = A.MostDerivedIsArrayElement; if (IsArray && A.MostDerivedPathLength != A.Entries.size()) // A is a subobject of the array element. return false; @@ -2713,8 +2799,7 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // Check for special cases where there is no existing APValue to look at. const Expr *Base = LVal.Base.dyn_cast<const Expr*>(); - if (!LVal.Designator.Invalid && Base && !LVal.CallIndex && - !Type.isVolatileQualified()) { + if (Base && !LVal.CallIndex && !Type.isVolatileQualified()) { if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(Base)) { // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the // initializer until now for such expressions. Such an expression can't be @@ -2959,7 +3044,7 @@ struct IncDecSubobjectHandler { if (!WasNegative && Value.isNegative() && isOverflowingIntegerType(Info.Ctx, SubobjType)) { APSInt ActualValue(Value, /*IsUnsigned*/true); - HandleOverflow(Info, E, ActualValue, SubobjType); + return HandleOverflow(Info, E, ActualValue, SubobjType); } } else { --Value; @@ -2969,7 +3054,7 @@ struct IncDecSubobjectHandler { unsigned BitWidth = Value.getBitWidth(); APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false); ActualValue.setBit(BitWidth); - HandleOverflow(Info, E, ActualValue, SubobjType); + return HandleOverflow(Info, E, ActualValue, SubobjType); } } return true; @@ -3253,12 +3338,21 @@ static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, return EvaluateAsBooleanCondition(Cond, Result, Info); } -static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, +/// \brief A location where the result (returned value) of evaluating a +/// statement should be stored. +struct StmtResult { + /// The APValue that should be filled in with the returned value. + APValue &Value; + /// The location containing the result, if any (used to support RVO). + const LValue *Slot; +}; + +static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, 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, +static EvalStmtResult EvaluateLoopBody(StmtResult &Result, EvalInfo &Info, const Stmt *Body, const SwitchCase *Case = nullptr) { BlockScopeRAII Scope(Info); @@ -3277,7 +3371,7 @@ static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info, } /// Evaluate a switch statement. -static EvalStmtResult EvaluateSwitch(APValue &Result, EvalInfo &Info, +static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, const SwitchStmt *SS) { BlockScopeRAII Scope(Info); @@ -3334,7 +3428,7 @@ static EvalStmtResult EvaluateSwitch(APValue &Result, EvalInfo &Info, } // Evaluate a statement. -static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, +static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const Stmt *S, const SwitchCase *Case) { if (!Info.nextStep(S)) return ESR_Failed; @@ -3440,7 +3534,10 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, case Stmt::ReturnStmtClass: { const Expr *RetExpr = cast<ReturnStmt>(S)->getRetValue(); FullExpressionRAII Scope(Info); - if (RetExpr && !Evaluate(Result, Info, RetExpr)) + if (RetExpr && + !(Result.Slot + ? EvaluateInPlace(Result.Value, Info, *Result.Slot, RetExpr) + : Evaluate(Result.Value, Info, RetExpr))) return ESR_Failed; return ESR_Returned; } @@ -3710,7 +3807,8 @@ static bool EvaluateArgs(ArrayRef<const Expr*> Args, ArgVector &ArgValues, static bool HandleFunctionCall(SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, ArrayRef<const Expr*> Args, const Stmt *Body, - EvalInfo &Info, APValue &Result) { + EvalInfo &Info, APValue &Result, + const LValue *ResultSlot) { ArgVector ArgValues(Args.size()); if (!EvaluateArgs(Args, ArgValues, Info)) return false; @@ -3745,7 +3843,8 @@ static bool HandleFunctionCall(SourceLocation CallLoc, return true; } - EvalStmtResult ESR = EvaluateStmt(Result, Info, Body); + StmtResult Ret = {Result, ResultSlot}; + EvalStmtResult ESR = EvaluateStmt(Ret, Info, Body); if (ESR == ESR_Succeeded) { if (Callee->getReturnType()->isVoidType()) return true; @@ -3774,6 +3873,11 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues.data()); + // FIXME: Creating an APValue just to hold a nonexistent return value is + // wasteful. + APValue RetVal; + StmtResult Ret = {RetVal, nullptr}; + // If it's a delegating constructor, just delegate. if (Definition->isDelegatingConstructor()) { CXXConstructorDecl::init_const_iterator I = Definition->init_begin(); @@ -3782,7 +3886,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, if (!EvaluateInPlace(Result, Info, This, (*I)->getInit())) return false; } - return EvaluateStmt(Result, Info, Definition->getBody()) != ESR_Failed; + return EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed; } // For a trivial copy or move constructor, perform an APValue copy. This is @@ -3890,7 +3994,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, } return Success && - EvaluateStmt(Result, Info, Definition->getBody()) != ESR_Failed; + EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed; } //===----------------------------------------------------------------------===// @@ -3902,11 +4006,12 @@ template <class Derived> class ExprEvaluatorBase : public ConstStmtVisitor<Derived, bool> { private: + Derived &getDerived() { return static_cast<Derived&>(*this); } bool DerivedSuccess(const APValue &V, const Expr *E) { - return static_cast<Derived*>(this)->Success(V, E); + return getDerived().Success(V, E); } bool DerivedZeroInitialization(const Expr *E) { - return static_cast<Derived*>(this)->ZeroInitialization(E); + return getDerived().ZeroInitialization(E); } // Check whether a conditional operator with a non-constant condition is a @@ -4087,6 +4192,14 @@ public: } bool VisitCallExpr(const CallExpr *E) { + APValue Result; + if (!handleCallExpr(E, Result, nullptr)) + return false; + return DerivedSuccess(Result, E); + } + + bool handleCallExpr(const CallExpr *E, APValue &Result, + const LValue *ResultSlot) { const Expr *Callee = E->getCallee()->IgnoreParens(); QualType CalleeType = Callee->getType(); @@ -4161,14 +4274,13 @@ public: const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); - APValue Result; if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) || - !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, - Info, Result)) + !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, + Result, ResultSlot)) return false; - return DerivedSuccess(Result, E); + return true; } bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { @@ -4293,7 +4405,8 @@ public: } APValue ReturnValue; - EvalStmtResult ESR = EvaluateStmt(ReturnValue, Info, *BI); + StmtResult Result = { ReturnValue, nullptr }; + EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI); if (ESR != ESR_Succeeded) { // FIXME: If the statement-expression terminated due to 'return', // 'break', or 'continue', it would be nice to propagate that to @@ -4345,20 +4458,24 @@ public: bool VisitMemberExpr(const MemberExpr *E) { // Handle non-static data members. QualType BaseTy; + bool EvalOK; if (E->isArrow()) { - if (!EvaluatePointer(E->getBase(), Result, this->Info)) - return false; + EvalOK = EvaluatePointer(E->getBase(), Result, this->Info); BaseTy = E->getBase()->getType()->castAs<PointerType>()->getPointeeType(); } else if (E->getBase()->isRValue()) { assert(E->getBase()->getType()->isRecordType()); - if (!EvaluateTemporary(E->getBase(), Result, this->Info)) - return false; + EvalOK = EvaluateTemporary(E->getBase(), Result, this->Info); BaseTy = E->getBase()->getType(); } else { - if (!this->Visit(E->getBase())) - return false; + EvalOK = this->Visit(E->getBase()); BaseTy = E->getBase()->getType(); } + if (!EvalOK) { + if (!this->Info.allowInvalidBaseExpr()) + return false; + Result.setInvalid(E); + return true; + } const ValueDecl *MD = E->getMemberDecl(); if (const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) { @@ -4498,12 +4615,13 @@ public: } // end anonymous namespace /// Evaluate an expression as an lvalue. This can be legitimately called on -/// expressions which are not glvalues, in two cases: +/// expressions which are not glvalues, in three cases: /// * function designators in C, and /// * "extern void" objects +/// * @selector() expressions in Objective-C static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info) { assert(E->isGLValue() || E->getType()->isFunctionType() || - E->getType()->isVoidType()); + E->getType()->isVoidType() || isa<ObjCSelectorExpr>(E)); return LValueExprEvaluator(Info, Result).Visit(E); } @@ -4770,7 +4888,7 @@ public: bool VisitObjCStringLiteral(const ObjCStringLiteral *E) { return Success(E); } bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E) - { return Success(E); } + { return Success(E); } bool VisitAddrLabelExpr(const AddrLabelExpr *E) { return Success(E); } bool VisitCallExpr(const CallExpr *E); @@ -4896,6 +5014,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { unsigned Size = Info.Ctx.getTypeSize(E->getType()); uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue(); Result.Base = (Expr*)nullptr; + Result.InvalidBase = false; Result.Offset = CharUnits::fromQuantity(N); Result.CallIndex = 0; Result.Designator.setInvalid(); @@ -5148,6 +5267,9 @@ namespace { } bool ZeroInitialization(const Expr *E); + bool VisitCallExpr(const CallExpr *E) { + return handleCallExpr(E, Result, &This); + } bool VisitCastExpr(const CastExpr *E); bool VisitInitListExpr(const InitListExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E); @@ -5504,7 +5626,7 @@ namespace { VectorExprEvaluator(EvalInfo &info, APValue &Result) : ExprEvaluatorBaseTy(info), Result(Result) {} - bool Success(const ArrayRef<APValue> &V, const Expr *E) { + bool Success(ArrayRef<APValue> V, const Expr *E) { assert(V.size() == E->getType()->castAs<VectorType>()->getNumElements()); // FIXME: remove this APValue copy. Result = APValue(V.data(), V.size()); @@ -5533,7 +5655,7 @@ static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) { return VectorExprEvaluator(Info, Result).Visit(E); } -bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { +bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) { const VectorType *VTy = E->getType()->castAs<VectorType>(); unsigned NElts = VTy->getNumElements(); @@ -5546,13 +5668,13 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { if (SETy->isIntegerType()) { APSInt IntResult; if (!EvaluateInteger(SE, IntResult, Info)) - return false; - Val = APValue(IntResult); + return false; + Val = APValue(std::move(IntResult)); } else if (SETy->isRealFloatingType()) { - APFloat F(0.0); - if (!EvaluateFloat(SE, F, Info)) - return false; - Val = APValue(F); + APFloat FloatResult(0.0); + if (!EvaluateFloat(SE, FloatResult, Info)) + return false; + Val = APValue(std::move(FloatResult)); } else { return Error(E); } @@ -5710,6 +5832,9 @@ namespace { return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, &VIE); } + bool VisitCallExpr(const CallExpr *E) { + return handleCallExpr(E, Result, &This); + } bool VisitInitListExpr(const InitListExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E, @@ -5998,8 +6123,7 @@ public: bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); private: - static QualType GetObjectType(APValue::LValueBase B); - bool TryEvaluateBuiltinObjectSize(const CallExpr *E); + bool TryEvaluateBuiltinObjectSize(const CallExpr *E, unsigned Type); // FIXME: Missing: array subscript of vector, member of vector }; } // end anonymous namespace @@ -6151,8 +6275,8 @@ static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) { APValue &V = Result.Val; if (V.getKind() == APValue::Int) return true; - - return EvaluateBuiltinConstantPForLValue(V); + if (V.getKind() == APValue::LValue) + return EvaluateBuiltinConstantPForLValue(V); } else if (ArgType->isFloatingType() || ArgType->isAnyComplexType()) { return Arg->isEvaluatable(Ctx); } else if (ArgType->isPointerType() || Arg->isGLValue()) { @@ -6171,7 +6295,7 @@ static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) { /// Retrieves the "underlying object type" of the given expression, /// as used by __builtin_object_size. -QualType IntExprEvaluator::GetObjectType(APValue::LValueBase B) { +static QualType getObjectType(APValue::LValueBase B) { if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) return VD->getType(); @@ -6183,49 +6307,258 @@ QualType IntExprEvaluator::GetObjectType(APValue::LValueBase B) { return QualType(); } -bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) { - LValue Base; +/// A more selective version of E->IgnoreParenCasts for +/// TryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only +/// to change the type of E. +/// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo` +/// +/// Always returns an RValue with a pointer representation. +static const Expr *ignorePointerCastsAndParens(const Expr *E) { + assert(E->isRValue() && E->getType()->hasPointerRepresentation()); + auto *NoParens = E->IgnoreParens(); + auto *Cast = dyn_cast<CastExpr>(NoParens); + if (Cast == nullptr) + return NoParens; + + // We only conservatively allow a few kinds of casts, because this code is + // inherently a simple solution that seeks to support the common case. + auto CastKind = Cast->getCastKind(); + if (CastKind != CK_NoOp && CastKind != CK_BitCast && + CastKind != CK_AddressSpaceConversion) + return NoParens; + + auto *SubExpr = Cast->getSubExpr(); + if (!SubExpr->getType()->hasPointerRepresentation() || !SubExpr->isRValue()) + return NoParens; + return ignorePointerCastsAndParens(SubExpr); +} + +/// Checks to see if the given LValue's Designator is at the end of the LValue's +/// record layout. e.g. +/// struct { struct { int a, b; } fst, snd; } obj; +/// obj.fst // no +/// obj.snd // yes +/// obj.fst.a // no +/// obj.fst.b // no +/// obj.snd.a // no +/// obj.snd.b // yes +/// +/// Please note: this function is specialized for how __builtin_object_size +/// views "objects". +static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { + assert(!LVal.Designator.Invalid); + + auto IsLastFieldDecl = [&Ctx](const FieldDecl *FD) { + if (FD->getParent()->isUnion()) + return true; + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(FD->getParent()); + return FD->getFieldIndex() + 1 == Layout.getFieldCount(); + }; + + auto &Base = LVal.getLValueBase(); + if (auto *ME = dyn_cast_or_null<MemberExpr>(Base.dyn_cast<const Expr *>())) { + if (auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) { + if (!IsLastFieldDecl(FD)) + return false; + } else if (auto *IFD = dyn_cast<IndirectFieldDecl>(ME->getMemberDecl())) { + for (auto *FD : IFD->chain()) + if (!IsLastFieldDecl(cast<FieldDecl>(FD))) + return false; + } + } + + QualType BaseType = getType(Base); + for (int I = 0, E = LVal.Designator.Entries.size(); I != E; ++I) { + if (BaseType->isArrayType()) { + // Because __builtin_object_size treats arrays as objects, we can ignore + // the index iff this is the last array in the Designator. + if (I + 1 == E) + return true; + auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType)); + uint64_t Index = LVal.Designator.Entries[I].ArrayIndex; + if (Index + 1 != CAT->getSize()) + return false; + BaseType = CAT->getElementType(); + } else if (BaseType->isAnyComplexType()) { + auto *CT = BaseType->castAs<ComplexType>(); + uint64_t Index = LVal.Designator.Entries[I].ArrayIndex; + if (Index != 1) + return false; + BaseType = CT->getElementType(); + } else if (auto *FD = getAsField(LVal.Designator.Entries[I])) { + if (!IsLastFieldDecl(FD)) + return false; + BaseType = FD->getType(); + } else { + assert(getAsBaseClass(LVal.Designator.Entries[I]) != nullptr && + "Expecting cast to a base class"); + return false; + } + } + return true; +} + +/// Tests to see if the LValue has a designator (that isn't necessarily valid). +static bool refersToCompleteObject(const LValue &LVal) { + if (LVal.Designator.Invalid || !LVal.Designator.Entries.empty()) + return false; + + if (!LVal.InvalidBase) + return true; + + auto *E = LVal.Base.dyn_cast<const Expr *>(); + (void)E; + assert(E != nullptr && isa<MemberExpr>(E)); + return false; +} + +/// Tries to evaluate the __builtin_object_size for @p E. If successful, returns +/// true and stores the result in @p Size. +/// +/// If @p WasError is non-null, this will report whether the failure to evaluate +/// is to be treated as an Error in IntExprEvaluator. +static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, + EvalInfo &Info, uint64_t &Size, + bool *WasError = nullptr) { + if (WasError != nullptr) + *WasError = false; + + auto Error = [&](const Expr *E) { + if (WasError != nullptr) + *WasError = true; + return false; + }; + + auto Success = [&](uint64_t S, const Expr *E) { + Size = S; + return true; + }; + + // Determine the denoted object. + LValue Base; { // The operand of __builtin_object_size is never evaluated for side-effects. // If there are any, but we can determine the pointed-to object anyway, then // ignore the side-effects. SpeculativeEvaluationRAII SpeculativeEval(Info); - if (!EvaluatePointer(E->getArg(0), Base, Info)) + FoldOffsetRAII Fold(Info, Type & 1); + + if (E->isGLValue()) { + // It's possible for us to be given GLValues if we're called via + // Expr::tryEvaluateObjectSize. + APValue RVal; + if (!EvaluateAsRValue(Info, E, RVal)) + return false; + Base.setFrom(Info.Ctx, RVal); + } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), Base, Info)) return false; } - if (!Base.getLValueBase()) { - // It is not possible to determine which objects ptr points to at compile time, - // __builtin_object_size should return (size_t) -1 for type 0 or 1 - // and (size_t) 0 for type 2 or 3. - llvm::APSInt TypeIntVaue; - const Expr *ExprType = E->getArg(1); - if (!ExprType->EvaluateAsInt(TypeIntVaue, Info.Ctx)) - return false; - if (TypeIntVaue == 0 || TypeIntVaue == 1) - return Success(-1, E); - if (TypeIntVaue == 2 || TypeIntVaue == 3) - return Success(0, E); + CharUnits BaseOffset = Base.getLValueOffset(); + // If we point to before the start of the object, there are no accessible + // bytes. + if (BaseOffset.isNegative()) + return Success(0, E); + + // In the case where we're not dealing with a subobject, we discard the + // subobject bit. + bool SubobjectOnly = (Type & 1) != 0 && !refersToCompleteObject(Base); + + // If Type & 1 is 0, we need to be able to statically guarantee that the bytes + // exist. If we can't verify the base, then we can't do that. + // + // As a special case, we produce a valid object size for an unknown object + // with a known designator if Type & 1 is 1. For instance: + // + // extern struct X { char buff[32]; int a, b, c; } *p; + // int a = __builtin_object_size(p->buff + 4, 3); // returns 28 + // int b = __builtin_object_size(p->buff + 4, 2); // returns 0, not 40 + // + // This matches GCC's behavior. + if (Base.InvalidBase && !SubobjectOnly) return Error(E); + + // If we're not examining only the subobject, then we reset to a complete + // object designator + // + // If Type is 1 and we've lost track of the subobject, just find the complete + // object instead. (If Type is 3, that's not correct behavior and we should + // return 0 instead.) + LValue End = Base; + if (!SubobjectOnly || (End.Designator.Invalid && Type == 1)) { + QualType T = getObjectType(End.getLValueBase()); + if (T.isNull()) + End.Designator.setInvalid(); + else { + End.Designator = SubobjectDesignator(T); + End.Offset = CharUnits::Zero(); + } } - QualType T = GetObjectType(Base.getLValueBase()); - if (T.isNull() || - T->isIncompleteType() || - T->isFunctionType() || - T->isVariablyModifiedType() || - T->isDependentType()) + // If it is not possible to determine which objects ptr points to at compile + // time, __builtin_object_size should return (size_t) -1 for type 0 or 1 + // and (size_t) 0 for type 2 or 3. + if (End.Designator.Invalid) + return false; + + // According to the GCC documentation, we want the size of the subobject + // denoted by the pointer. But that's not quite right -- what we actually + // want is the size of the immediately-enclosing array, if there is one. + int64_t AmountToAdd = 1; + if (End.Designator.MostDerivedIsArrayElement && + End.Designator.Entries.size() == End.Designator.MostDerivedPathLength) { + // We got a pointer to an array. Step to its end. + AmountToAdd = End.Designator.MostDerivedArraySize - + End.Designator.Entries.back().ArrayIndex; + } else if (End.Designator.isOnePastTheEnd()) { + // We're already pointing at the end of the object. + AmountToAdd = 0; + } + + QualType PointeeType = End.Designator.MostDerivedType; + assert(!PointeeType.isNull()); + if (PointeeType->isIncompleteType() || PointeeType->isFunctionType()) return Error(E); - CharUnits Size = Info.Ctx.getTypeSizeInChars(T); - CharUnits Offset = Base.getLValueOffset(); + if (!HandleLValueArrayAdjustment(Info, E, End, End.Designator.MostDerivedType, + AmountToAdd)) + return false; - if (!Offset.isNegative() && Offset <= Size) - Size -= Offset; - else - Size = CharUnits::Zero(); - return Success(Size, E); + auto EndOffset = End.getLValueOffset(); + + // The following is a moderately common idiom in C: + // + // struct Foo { int a; char c[1]; }; + // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar)); + // strcpy(&F->c[0], Bar); + // + // So, if we see that we're examining a 1-length (or 0-length) array at the + // end of a struct with an unknown base, we give up instead of breaking code + // that behaves this way. Note that we only do this when Type=1, because + // Type=3 is a lower bound, so answering conservatively is fine. + if (End.InvalidBase && SubobjectOnly && Type == 1 && + End.Designator.Entries.size() == End.Designator.MostDerivedPathLength && + End.Designator.MostDerivedIsArrayElement && + End.Designator.MostDerivedArraySize < 2 && + isDesignatorAtObjectEnd(Info.Ctx, End)) + return false; + + if (BaseOffset > EndOffset) + return Success(0, E); + + return Success((EndOffset - BaseOffset).getQuantity(), E); +} + +bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E, + unsigned Type) { + uint64_t Size; + bool WasError; + if (::tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size, &WasError)) + return Success(Size, E); + if (WasError) + return Error(E); + return false; } bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { @@ -6234,17 +6567,16 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { return ExprEvaluatorBaseTy::VisitCallExpr(E); case Builtin::BI__builtin_object_size: { - if (TryEvaluateBuiltinObjectSize(E)) + // The type was checked when we built the expression. + unsigned Type = + E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); + assert(Type <= 3 && "unexpected type"); + + if (TryEvaluateBuiltinObjectSize(E, Type)) return true; - // If evaluating the argument has side-effects, we can't determine the size - // of the object, and so we lower it to unknown now. CodeGen relies on us to - // handle all cases where the expression has side-effects. - if (E->getArg(0)->HasSideEffects(Info.Ctx)) { - if (E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue() <= 1) - return Success(-1ULL, E); - return Success(0, E); - } + if (E->getArg(0)->HasSideEffects(Info.Ctx)) + return Success((Type & 2) ? 0 : -1, E); // Expression had no side effects, but we couldn't statically determine the // size of the referenced object. @@ -6254,10 +6586,13 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case EvalInfo::EM_ConstantFold: case EvalInfo::EM_EvaluateForOverflow: case EvalInfo::EM_IgnoreSideEffects: + case EvalInfo::EM_DesignatorFold: + // Leave it to IR generation. return Error(E); case EvalInfo::EM_ConstantExpressionUnevaluated: case EvalInfo::EM_PotentialConstantExpressionUnevaluated: - return Success(-1ULL, E); + // Reduce it to a constant now. + return Success((Type & 2) ? 0 : -1, E); } } @@ -6523,9 +6858,15 @@ static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx, !LV.getLValueDesignator().isOnePastTheEnd()) return false; + // A pointer to an incomplete type might be past-the-end if the type's size is + // zero. We cannot tell because the type is incomplete. + QualType Ty = getType(LV.getLValueBase()); + if (Ty->isIncompleteType()) + return true; + // We're a past-the-end pointer if we point to the byte after the object, // no matter what our type or path is. - auto Size = Ctx.getTypeSizeInChars(getType(LV.getLValueBase())); + auto Size = Ctx.getTypeSizeInChars(Ty); return LV.getLValueOffset() == Size; } @@ -6555,7 +6896,13 @@ class DataRecursiveIntBinOpEvaluator { EvalResult LHSResult; // meaningful only for binary operator expression. enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind; - Job() : StoredInfo(nullptr) {} + Job() = default; + Job(Job &&J) + : E(J.E), LHSResult(J.LHSResult), Kind(J.Kind), + StoredInfo(J.StoredInfo), OldEvalStatus(J.OldEvalStatus) { + J.StoredInfo = nullptr; + } + void startSpeculativeEval(EvalInfo &Info) { OldEvalStatus = Info.EvalStatus; Info.EvalStatus.Diag = nullptr; @@ -6567,7 +6914,7 @@ class DataRecursiveIntBinOpEvaluator { } } private: - EvalInfo *StoredInfo; // non-null if status changed. + EvalInfo *StoredInfo = nullptr; // non-null if status changed. Expr::EvalStatus OldEvalStatus; }; @@ -6946,7 +7293,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { LValue LHSValue, RHSValue; bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info); - if (!LHSOK && Info.keepEvaluatingAfterFailure()) + if (!LHSOK && !Info.keepEvaluatingAfterFailure()) return false; if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK) @@ -6958,21 +7305,20 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->getOpcode() == BO_Sub) { // Handle &&A - &&B. if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero()) - return false; + return Error(E); const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr*>(); const Expr *RHSExpr = RHSValue.Base.dyn_cast<const Expr*>(); if (!LHSExpr || !RHSExpr) - return false; + return Error(E); const AddrLabelExpr *LHSAddrExpr = dyn_cast<AddrLabelExpr>(LHSExpr); const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr); if (!LHSAddrExpr || !RHSAddrExpr) - return false; + return Error(E); // Make sure both labels come from the same function. if (LHSAddrExpr->getLabel()->getDeclContext() != RHSAddrExpr->getLabel()->getDeclContext()) - return false; - Result = APValue(LHSAddrExpr, RHSAddrExpr); - return true; + return Error(E); + return Success(APValue(LHSAddrExpr, RHSAddrExpr), E); } // Inequalities and subtractions between unrelated pointers have // unspecified or undefined behavior. @@ -7063,8 +7409,9 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { APSInt TrueResult = (LHS - RHS) / ElemSize; APSInt Result = TrueResult.trunc(Info.Ctx.getIntWidth(E->getType())); - if (Result.extend(65) != TrueResult) - HandleOverflow(Info, E, TrueResult, E->getType()); + if (Result.extend(65) != TrueResult && + !HandleOverflow(Info, E, TrueResult, E->getType())) + return false; return Success(Result, E); } @@ -7270,9 +7617,9 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { return Error(OOE); QualType CurrentType = OOE->getTypeSourceInfo()->getType(); for (unsigned i = 0; i != n; ++i) { - OffsetOfExpr::OffsetOfNode ON = OOE->getComponent(i); + OffsetOfNode ON = OOE->getComponent(i); switch (ON.getKind()) { - case OffsetOfExpr::OffsetOfNode::Array: { + case OffsetOfNode::Array: { const Expr *Idx = OOE->getIndexExpr(ON.getArrayExprIndex()); APSInt IdxResult; if (!EvaluateInteger(Idx, IdxResult, Info)) @@ -7286,7 +7633,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { break; } - case OffsetOfExpr::OffsetOfNode::Field: { + case OffsetOfNode::Field: { FieldDecl *MemberDecl = ON.getField(); const RecordType *RT = CurrentType->getAs<RecordType>(); if (!RT) @@ -7301,10 +7648,10 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { break; } - case OffsetOfExpr::OffsetOfNode::Identifier: + case OffsetOfNode::Identifier: llvm_unreachable("dependent __builtin_offsetof"); - case OffsetOfExpr::OffsetOfNode::Base: { + case OffsetOfNode::Base: { CXXBaseSpecifier *BaseSpec = ON.getBase(); if (BaseSpec->isVirtual()) return Error(OOE); @@ -7350,9 +7697,10 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { return false; if (!Result.isInt()) return Error(E); const APSInt &Value = Result.getInt(); - if (Value.isSigned() && Value.isMinSignedValue()) - HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), - E->getType()); + if (Value.isSigned() && Value.isMinSignedValue() && + !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), + E->getType())) + return false; return Success(-Value, E); } case UO_Not: { @@ -7433,12 +7781,16 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_PointerToBoolean: case CK_IntegralToBoolean: case CK_FloatingToBoolean: + case CK_BooleanToSignedIntegral: case CK_FloatingComplexToBoolean: case CK_IntegralComplexToBoolean: { bool BoolResult; if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info)) return false; - return Success(BoolResult, E); + uint64_t IntResult = BoolResult; + if (BoolResult && E->getCastKind() == CK_BooleanToSignedIntegral) + IntResult = (uint64_t)-1; + return Success(IntResult, E); } case CK_IntegralCast: { @@ -7875,6 +8227,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_ToVoid: case CK_VectorSplat: case CK_IntegralCast: + case CK_BooleanToSignedIntegral: case CK_IntegralToBoolean: case CK_IntegralToFloating: case CK_FloatingToIntegral: @@ -8512,6 +8865,12 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result, HandleConversionToBool(Scratch.Val, Result); } +static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result, + Expr::SideEffectsKind SEK) { + return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) || + (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior); +} + bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects) const { if (!getType()->isIntegralOrEnumerationType()) @@ -8519,7 +8878,7 @@ bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx, EvalResult ExprResult; if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() || - (!AllowSideEffects && ExprResult.HasSideEffects)) + hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) return false; Result = ExprResult.Val.getInt(); @@ -8551,7 +8910,9 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, Expr::EvalStatus EStatus; EStatus.Diag = &Notes; - EvalInfo InitInfo(Ctx, EStatus, EvalInfo::EM_ConstantFold); + EvalInfo InitInfo(Ctx, EStatus, VD->isConstexpr() + ? EvalInfo::EM_ConstantExpression + : EvalInfo::EM_ConstantFold); InitInfo.setEvaluatingDecl(VD, Value); LValue LVal; @@ -8580,9 +8941,10 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be /// constant folded, but discard the result. -bool Expr::isEvaluatable(const ASTContext &Ctx) const { +bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const { EvalResult Result; - return EvaluateAsRValue(Result, Ctx) && !Result.HasSideEffects; + return EvaluateAsRValue(Result, Ctx) && + !hasUnacceptableSideEffect(Result, SEK); } APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, @@ -8677,6 +9039,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::ImaginaryLiteralClass: case Expr::StringLiteralClass: case Expr::ArraySubscriptExprClass: + case Expr::OMPArraySectionExprClass: case Expr::MemberExprClass: case Expr::CompoundAssignOperatorClass: case Expr::CompoundLiteralExprClass: @@ -8695,6 +9058,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: case Expr::MSPropertyRefExprClass: + case Expr::MSPropertySubscriptExprClass: case Expr::CXXNullPtrLiteralExprClass: case Expr::UserDefinedLiteralClass: case Expr::CXXThisExprClass: @@ -8740,6 +9104,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::AtomicExprClass: case Expr::LambdaExprClass: case Expr::CXXFoldExprClass: + case Expr::CoawaitExprClass: + case Expr::CoyieldExprClass: return ICEDiag(IK_NotICE, E->getLocStart()); case Expr::InitListExprClass: { @@ -8825,6 +9191,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case UO_PreDec: case UO_AddrOf: case UO_Deref: + case UO_Coawait: // C99 6.6/3 allows increment and decrement within unevaluated // subexpressions of constant expressions, but they can never be ICEs // because an ICE cannot contain an lvalue operand. @@ -9078,7 +9445,11 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx, if (!isIntegerConstantExpr(Ctx, Loc)) return false; - if (!EvaluateAsInt(Value, Ctx)) + // The only possible side-effects here are due to UB discovered in the + // evaluation (for instance, INT_MAX + 1). In such a case, we are still + // required to treat the expression as an ICE, so we produce the folded + // value. + if (!EvaluateAsInt(Value, Ctx, SE_AllowSideEffects)) llvm_unreachable("ICE cannot be evaluated!"); return true; } @@ -9172,7 +9543,7 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, HandleConstructorCall(Loc, This, Args, CD, Info, Scratch); } else HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr, - Args, FD->getBody(), Info, Scratch); + Args, FD->getBody(), Info, Scratch, nullptr); return Diags.empty(); } @@ -9200,3 +9571,13 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E, Evaluate(ResultScratch, Info, E); return Diags.empty(); } + +bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, + unsigned Type) const { + if (!getType()->isPointerType()) + return false; + + Expr::EvalStatus Status; + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); + return ::tryEvaluateBuiltinObjectSize(this, Type, Info, Result); +} diff --git a/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp b/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp new file mode 100644 index 0000000..0936a81 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp @@ -0,0 +1,360 @@ +//===--- ExprObjC.cpp - (ObjC) Expression AST Node Implementation ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the subclesses of Expr class declared in ExprObjC.h +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ExprObjC.h" + +#include "clang/AST/ASTContext.h" + +using namespace clang; + +ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr *> Elements, QualType T, + ObjCMethodDecl *Method, SourceRange SR) + : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary, false, false, + false, false), + NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method) { + Expr **SaveElements = getElements(); + for (unsigned I = 0, N = Elements.size(); I != N; ++I) { + if (Elements[I]->isTypeDependent() || Elements[I]->isValueDependent()) + ExprBits.ValueDependent = true; + if (Elements[I]->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (Elements[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SaveElements[I] = Elements[I]; + } +} + +ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C, + ArrayRef<Expr *> Elements, + QualType T, ObjCMethodDecl *Method, + SourceRange SR) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Elements.size())); + return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR); +} + +ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C, + unsigned NumElements) { + + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumElements)); + return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements); +} + +ObjCDictionaryLiteral::ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK, + bool HasPackExpansions, QualType T, + ObjCMethodDecl *method, + SourceRange SR) + : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary, false, false, + false, false), + NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR), + DictWithObjectsMethod(method) { + KeyValuePair *KeyValues = getTrailingObjects<KeyValuePair>(); + ExpansionData *Expansions = + HasPackExpansions ? getTrailingObjects<ExpansionData>() : nullptr; + for (unsigned I = 0; I < NumElements; I++) { + if (VK[I].Key->isTypeDependent() || VK[I].Key->isValueDependent() || + VK[I].Value->isTypeDependent() || VK[I].Value->isValueDependent()) + ExprBits.ValueDependent = true; + if (VK[I].Key->isInstantiationDependent() || + VK[I].Value->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (VK[I].EllipsisLoc.isInvalid() && + (VK[I].Key->containsUnexpandedParameterPack() || + VK[I].Value->containsUnexpandedParameterPack())) + ExprBits.ContainsUnexpandedParameterPack = true; + + KeyValues[I].Key = VK[I].Key; + KeyValues[I].Value = VK[I].Value; + if (Expansions) { + Expansions[I].EllipsisLoc = VK[I].EllipsisLoc; + if (VK[I].NumExpansions) + Expansions[I].NumExpansionsPlusOne = *VK[I].NumExpansions + 1; + else + Expansions[I].NumExpansionsPlusOne = 0; + } + } +} + +ObjCDictionaryLiteral * +ObjCDictionaryLiteral::Create(const ASTContext &C, + ArrayRef<ObjCDictionaryElement> VK, + bool HasPackExpansions, QualType T, + ObjCMethodDecl *method, SourceRange SR) { + void *Mem = C.Allocate(totalSizeToAlloc<KeyValuePair, ExpansionData>( + VK.size(), HasPackExpansions ? VK.size() : 0)); + return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR); +} + +ObjCDictionaryLiteral * +ObjCDictionaryLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements, + bool HasPackExpansions) { + void *Mem = C.Allocate(totalSizeToAlloc<KeyValuePair, ExpansionData>( + NumElements, HasPackExpansions ? NumElements : 0)); + return new (Mem) + ObjCDictionaryLiteral(EmptyShell(), NumElements, HasPackExpansions); +} + +QualType ObjCPropertyRefExpr::getReceiverType(const ASTContext &ctx) const { + if (isClassReceiver()) + return ctx.getObjCInterfaceType(getClassReceiver()); + + if (isSuperReceiver()) + return getSuperReceiverType(); + + return getBase()->getType(); +} + +ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK, + SourceLocation LBracLoc, + SourceLocation SuperLoc, bool IsInstanceSuper, + QualType SuperType, Selector Sel, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, + /*TypeDependent=*/false, /*ValueDependent=*/false, + /*InstantiationDependent=*/false, + /*ContainsUnexpandedParameterPack=*/false), + SelectorOrMethod( + reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())), + Kind(IsInstanceSuper ? SuperInstance : SuperClass), + HasMethod(Method != nullptr), IsDelegateInitCall(false), + IsImplicit(isImplicit), SuperLoc(SuperLoc), LBracLoc(LBracLoc), + RBracLoc(RBracLoc) { + initArgsAndSelLocs(Args, SelLocs, SelLocsK); + setReceiverPointer(SuperType.getAsOpaquePtr()); +} + +ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, Selector Sel, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(), + T->isDependentType(), T->isInstantiationDependentType(), + T->containsUnexpandedParameterPack()), + SelectorOrMethod( + reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())), + Kind(Class), HasMethod(Method != nullptr), IsDelegateInitCall(false), + IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { + initArgsAndSelLocs(Args, SelLocs, SelLocsK); + setReceiverPointer(Receiver); +} + +ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK, + SourceLocation LBracLoc, Expr *Receiver, + Selector Sel, ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, + Receiver->isTypeDependent(), Receiver->isTypeDependent(), + Receiver->isInstantiationDependent(), + Receiver->containsUnexpandedParameterPack()), + SelectorOrMethod( + reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())), + Kind(Instance), HasMethod(Method != nullptr), IsDelegateInitCall(false), + IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { + initArgsAndSelLocs(Args, SelLocs, SelLocsK); + setReceiverPointer(Receiver); +} + +void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK) { + setNumArgs(Args.size()); + Expr **MyArgs = getArgs(); + for (unsigned I = 0; I != Args.size(); ++I) { + if (Args[I]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (Args[I]->isValueDependent()) + ExprBits.ValueDependent = true; + if (Args[I]->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (Args[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + MyArgs[I] = Args[I]; + } + + SelLocsKind = SelLocsK; + if (!isImplicit()) { + if (SelLocsK == SelLoc_NonStandard) + std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs()); + } +} + +ObjCMessageExpr * +ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, + SourceLocation LBracLoc, SourceLocation SuperLoc, + bool IsInstanceSuper, QualType SuperType, Selector Sel, + ArrayRef<SourceLocation> SelLocs, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) { + assert((!SelLocs.empty() || isImplicit) && + "No selector locs for non-implicit message"); + ObjCMessageExpr *Mem; + SelectorLocationsKind SelLocsK = SelectorLocationsKind(); + if (isImplicit) + Mem = alloc(Context, Args.size(), 0); + else + Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper, + SuperType, Sel, SelLocs, SelLocsK, Method, + Args, RBracLoc, isImplicit); +} + +ObjCMessageExpr * +ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, + SourceLocation LBracLoc, TypeSourceInfo *Receiver, + Selector Sel, ArrayRef<SourceLocation> SelLocs, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) { + assert((!SelLocs.empty() || isImplicit) && + "No selector locs for non-implicit message"); + ObjCMessageExpr *Mem; + SelectorLocationsKind SelLocsK = SelectorLocationsKind(); + if (isImplicit) + Mem = alloc(Context, Args.size(), 0); + else + Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + return new (Mem) + ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method, + Args, RBracLoc, isImplicit); +} + +ObjCMessageExpr * +ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK, + SourceLocation LBracLoc, Expr *Receiver, Selector Sel, + ArrayRef<SourceLocation> SelLocs, + ObjCMethodDecl *Method, ArrayRef<Expr *> Args, + SourceLocation RBracLoc, bool isImplicit) { + assert((!SelLocs.empty() || isImplicit) && + "No selector locs for non-implicit message"); + ObjCMessageExpr *Mem; + SelectorLocationsKind SelLocsK = SelectorLocationsKind(); + if (isImplicit) + Mem = alloc(Context, Args.size(), 0); + else + Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + return new (Mem) + ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method, + Args, RBracLoc, isImplicit); +} + +ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(const ASTContext &Context, + unsigned NumArgs, + unsigned NumStoredSelLocs) { + ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs); + return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); +} + +ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, + ArrayRef<Expr *> Args, + SourceLocation RBraceLoc, + ArrayRef<SourceLocation> SelLocs, + Selector Sel, + SelectorLocationsKind &SelLocsK) { + SelLocsK = hasStandardSelectorLocs(Sel, SelLocs, Args, RBraceLoc); + unsigned NumStoredSelLocs = + (SelLocsK == SelLoc_NonStandard) ? SelLocs.size() : 0; + return alloc(C, Args.size(), NumStoredSelLocs); +} + +ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs, + unsigned NumStoredSelLocs) { + return (ObjCMessageExpr *)C.Allocate( + totalSizeToAlloc<void *, SourceLocation>(NumArgs + 1, NumStoredSelLocs), + llvm::AlignOf<ObjCMessageExpr>::Alignment); +} + +void ObjCMessageExpr::getSelectorLocs( + SmallVectorImpl<SourceLocation> &SelLocs) const { + for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i) + SelLocs.push_back(getSelectorLoc(i)); +} + +SourceRange ObjCMessageExpr::getReceiverRange() const { + switch (getReceiverKind()) { + case Instance: + return getInstanceReceiver()->getSourceRange(); + + case Class: + return getClassReceiverTypeInfo()->getTypeLoc().getSourceRange(); + + case SuperInstance: + case SuperClass: + return getSuperLoc(); + } + + llvm_unreachable("Invalid ReceiverKind!"); +} + +Selector ObjCMessageExpr::getSelector() const { + if (HasMethod) + return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod) + ->getSelector(); + return Selector(SelectorOrMethod); +} + +QualType ObjCMessageExpr::getReceiverType() const { + switch (getReceiverKind()) { + case Instance: + return getInstanceReceiver()->getType(); + case Class: + return getClassReceiver(); + case SuperInstance: + case SuperClass: + return getSuperType(); + } + + llvm_unreachable("unexpected receiver kind"); +} + +ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { + QualType T = getReceiverType(); + + if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>()) + return Ptr->getInterfaceDecl(); + + if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>()) + return Ty->getInterface(); + + return nullptr; +} + +Stmt::child_range ObjCMessageExpr::children() { + Stmt **begin; + if (getReceiverKind() == Instance) + begin = reinterpret_cast<Stmt **>(getTrailingObjects<void *>()); + else + begin = reinterpret_cast<Stmt **>(getArgs()); + return child_range(begin, + reinterpret_cast<Stmt **>(getArgs() + getNumArgs())); +} + +StringRef ObjCBridgedCastExpr::getBridgeKindName() const { + switch (getBridgeKind()) { + case OBC_Bridge: + return "__bridge"; + case OBC_BridgeTransfer: + return "__bridge_transfer"; + case OBC_BridgeRetained: + return "__bridge_retained"; + } + + llvm_unreachable("Invalid BridgeKind!"); +} diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp index 1c82c35..e3de8c5 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ExternalASTSource.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclarationName.h" +#include "clang/Basic/Module.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -27,9 +28,19 @@ ExternalASTSource::getSourceDescriptor(unsigned ID) { return None; } -ExternalASTSource::ASTSourceDescriptor -ExternalASTSource::getSourceDescriptor(const Module &M) { - return ASTSourceDescriptor(); +ExternalASTSource::ASTSourceDescriptor::ASTSourceDescriptor(const Module &M) + : Signature(M.Signature), ClangModule(&M) { + if (M.Directory) + Path = M.Directory->getName(); + if (auto *File = M.getASTFile()) + ASTFile = File->getName(); +} + +std::string ExternalASTSource::ASTSourceDescriptor::getModuleName() const { + if (ClangModule) + return ClangModule->Name; + else + return PCHModuleName; } void ExternalASTSource::FindFileRegionDecls(FileID File, unsigned Offset, @@ -92,17 +103,13 @@ ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC, return false; } -void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) { -} +void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) {} -ExternalLoadResult -ExternalASTSource::FindExternalLexicalDecls(const DeclContext *DC, - bool (*isKindWeWant)(Decl::Kind), - SmallVectorImpl<Decl*> &Result) { - return ELR_AlreadyLoaded; -} +void ExternalASTSource::FindExternalLexicalDecls( + const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, + SmallVectorImpl<Decl *> &Result) {} -void ExternalASTSource::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { } +void ExternalASTSource::getMemoryBufferSizes(MemoryBufferSizes &sizes) const {} uint32_t ExternalASTSource::incrementGeneration(ASTContext &C) { uint32_t OldGeneration = CurrentGeneration; diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp index 7503cbf..8a2cc0f 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp @@ -149,6 +149,20 @@ public: return nullptr; } + void addTypedefNameForUnnamedTagDecl(TagDecl *TD, + TypedefNameDecl *DD) override {} + + TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { + return nullptr; + } + + void addDeclaratorForUnnamedTagDecl(TagDecl *TD, + DeclaratorDecl *DD) override {} + + DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { + return nullptr; + } + MangleNumberingContext *createMangleNumberingContext() const override { return new ItaniumNumberingContext(); } diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index dac803e..3f6b682 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -174,8 +174,6 @@ public: void mangleStringLiteral(const StringLiteral *, raw_ostream &) override; - void mangleCXXVTableBitSet(const CXXRecordDecl *RD, raw_ostream &) override; - bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { // Lambda closure types are already numbered. if (isLambda(ND)) @@ -379,8 +377,8 @@ private: void mangleType(const TagType*); void mangleType(TemplateName); - void mangleBareFunctionType(const FunctionType *T, - bool MangleReturnType); + void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType, + const FunctionDecl *FD = nullptr); void mangleNeonVectorType(const VectorType *T); void mangleAArch64NeonVectorType(const VectorType *T); @@ -397,7 +395,8 @@ private: void mangleCXXCtorType(CXXCtorType T); void mangleCXXDtorType(CXXDtorType T); - void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs); + void mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs, + unsigned NumTemplateArgs); void mangleTemplateArgs(const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); void mangleTemplateArgs(const TemplateArgumentList &AL); @@ -525,7 +524,7 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { } mangleBareFunctionType(FD->getType()->getAs<FunctionType>(), - MangleReturnType); + MangleReturnType, FD); } static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) { @@ -700,8 +699,7 @@ void CXXNameMangler::mangleFloat(const llvm::APFloat &f) { assert(numCharacters != 0); // Allocate a buffer of the right number of characters. - SmallVector<char, 20> buffer; - buffer.set_size(numCharacters); + SmallVector<char, 20> buffer(numCharacters); // Fill the buffer left-to-right. for (unsigned stringIndex = 0; stringIndex != numCharacters; ++stringIndex) { @@ -1020,7 +1018,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, unsigned UnnamedMangle = getASTContext().getManglingNumber(TD); Out << "Ut"; if (UnnamedMangle > 1) - Out << llvm::utostr(UnnamedMangle - 2); + Out << UnnamedMangle - 2; Out << '_'; break; } @@ -1285,7 +1283,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { Out << "Ul"; const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()-> getAs<FunctionProtoType>(); - mangleBareFunctionType(Proto, /*MangleReturnType=*/false); + mangleBareFunctionType(Proto, /*MangleReturnType=*/false, + Lambda->getLambdaStaticInvoker()); Out << "E"; // The number is omitted for the first closure type with a given @@ -1510,6 +1509,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::ObjCInterface: case Type::ObjCObjectPointer: case Type::Atomic: + case Type::Pipe: llvm_unreachable("type is illegal as a nested name specifier"); case Type::SubstTemplateTypeParmPack: @@ -1756,6 +1756,9 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { // The conditional operator can't be overloaded, but we still handle it when // mangling expressions. case OO_Conditional: Out << "qu"; break; + // Proposal on cxx-abi-dev, 2015-10-21. + // ::= aw # co_await + case OO_Coawait: Out << "aw"; break; case OO_None: case NUM_OVERLOADED_OPERATORS: @@ -1988,34 +1991,79 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) // ::= u <source-name> # vendor extended type switch (T->getKind()) { - case BuiltinType::Void: Out << 'v'; break; - case BuiltinType::Bool: Out << 'b'; break; - case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'c'; break; - case BuiltinType::UChar: Out << 'h'; break; - case BuiltinType::UShort: Out << 't'; break; - case BuiltinType::UInt: Out << 'j'; break; - case BuiltinType::ULong: Out << 'm'; break; - case BuiltinType::ULongLong: Out << 'y'; break; - case BuiltinType::UInt128: Out << 'o'; break; - case BuiltinType::SChar: Out << 'a'; break; + case BuiltinType::Void: + Out << 'v'; + break; + case BuiltinType::Bool: + Out << 'b'; + break; + case BuiltinType::Char_U: + case BuiltinType::Char_S: + Out << 'c'; + break; + case BuiltinType::UChar: + Out << 'h'; + break; + case BuiltinType::UShort: + Out << 't'; + break; + case BuiltinType::UInt: + Out << 'j'; + break; + case BuiltinType::ULong: + Out << 'm'; + break; + case BuiltinType::ULongLong: + Out << 'y'; + break; + case BuiltinType::UInt128: + Out << 'o'; + break; + case BuiltinType::SChar: + Out << 'a'; + break; case BuiltinType::WChar_S: - case BuiltinType::WChar_U: Out << 'w'; break; - case BuiltinType::Char16: Out << "Ds"; break; - case BuiltinType::Char32: Out << "Di"; break; - case BuiltinType::Short: Out << 's'; break; - case BuiltinType::Int: Out << 'i'; break; - case BuiltinType::Long: Out << 'l'; break; - case BuiltinType::LongLong: Out << 'x'; break; - case BuiltinType::Int128: Out << 'n'; break; - case BuiltinType::Half: Out << "Dh"; break; - case BuiltinType::Float: Out << 'f'; break; - case BuiltinType::Double: Out << 'd'; break; + case BuiltinType::WChar_U: + Out << 'w'; + break; + case BuiltinType::Char16: + Out << "Ds"; + break; + case BuiltinType::Char32: + Out << "Di"; + break; + case BuiltinType::Short: + Out << 's'; + break; + case BuiltinType::Int: + Out << 'i'; + break; + case BuiltinType::Long: + Out << 'l'; + break; + case BuiltinType::LongLong: + Out << 'x'; + break; + case BuiltinType::Int128: + Out << 'n'; + break; + case BuiltinType::Half: + Out << "Dh"; + break; + case BuiltinType::Float: + Out << 'f'; + break; + case BuiltinType::Double: + Out << 'd'; + break; case BuiltinType::LongDouble: Out << (getASTContext().getTargetInfo().useFloat128ManglingForLongDouble() ? 'g' : 'e'); break; - case BuiltinType::NullPtr: Out << "Dn"; break; + case BuiltinType::NullPtr: + Out << "Dn"; + break; #define BUILTIN_TYPE(Id, SingletonId) #define PLACEHOLDER_TYPE(Id, SingletonId) \ @@ -2023,17 +2071,69 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { #include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: llvm_unreachable("mangling a placeholder type"); - case BuiltinType::ObjCId: Out << "11objc_object"; break; - case BuiltinType::ObjCClass: Out << "10objc_class"; break; - case BuiltinType::ObjCSel: Out << "13objc_selector"; break; - case BuiltinType::OCLImage1d: Out << "11ocl_image1d"; break; - case BuiltinType::OCLImage1dArray: Out << "16ocl_image1darray"; break; - case BuiltinType::OCLImage1dBuffer: Out << "17ocl_image1dbuffer"; break; - case BuiltinType::OCLImage2d: Out << "11ocl_image2d"; break; - case BuiltinType::OCLImage2dArray: Out << "16ocl_image2darray"; break; - case BuiltinType::OCLImage3d: Out << "11ocl_image3d"; break; - case BuiltinType::OCLSampler: Out << "11ocl_sampler"; break; - case BuiltinType::OCLEvent: Out << "9ocl_event"; break; + case BuiltinType::ObjCId: + Out << "11objc_object"; + break; + case BuiltinType::ObjCClass: + Out << "10objc_class"; + break; + case BuiltinType::ObjCSel: + Out << "13objc_selector"; + break; + case BuiltinType::OCLImage1d: + Out << "11ocl_image1d"; + break; + case BuiltinType::OCLImage1dArray: + Out << "16ocl_image1darray"; + break; + case BuiltinType::OCLImage1dBuffer: + Out << "17ocl_image1dbuffer"; + break; + case BuiltinType::OCLImage2d: + Out << "11ocl_image2d"; + break; + case BuiltinType::OCLImage2dArray: + Out << "16ocl_image2darray"; + break; + case BuiltinType::OCLImage2dDepth: + Out << "16ocl_image2ddepth"; + break; + case BuiltinType::OCLImage2dArrayDepth: + Out << "21ocl_image2darraydepth"; + break; + case BuiltinType::OCLImage2dMSAA: + Out << "15ocl_image2dmsaa"; + break; + case BuiltinType::OCLImage2dArrayMSAA: + Out << "20ocl_image2darraymsaa"; + break; + case BuiltinType::OCLImage2dMSAADepth: + Out << "20ocl_image2dmsaadepth"; + break; + case BuiltinType::OCLImage2dArrayMSAADepth: + Out << "35ocl_image2darraymsaadepth"; + break; + case BuiltinType::OCLImage3d: + Out << "11ocl_image3d"; + break; + case BuiltinType::OCLSampler: + Out << "11ocl_sampler"; + break; + case BuiltinType::OCLEvent: + Out << "9ocl_event"; + break; + case BuiltinType::OCLClkEvent: + Out << "12ocl_clkevent"; + break; + case BuiltinType::OCLQueue: + Out << "9ocl_queue"; + break; + case BuiltinType::OCLNDRange: + Out << "11ocl_ndrange"; + break; + case BuiltinType::OCLReserveID: + Out << "13ocl_reserveid"; + break; } } @@ -2056,11 +2156,26 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) { Out << 'E'; } + void CXXNameMangler::mangleType(const FunctionNoProtoType *T) { - llvm_unreachable("Can't mangle K&R function prototypes"); + // Function types without prototypes can arise when mangling a function type + // within an overloadable function in C. We mangle these as the absence of any + // parameter types (not even an empty parameter list). + Out << 'F'; + + FunctionTypeDepthState saved = FunctionTypeDepth.push(); + + FunctionTypeDepth.enterResultType(); + mangleType(T->getReturnType()); + FunctionTypeDepth.leaveResultType(); + + FunctionTypeDepth.pop(saved); + Out << 'E'; } + void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, - bool MangleReturnType) { + bool MangleReturnType, + const FunctionDecl *FD) { // We should never be mangling something without a prototype. const FunctionProtoType *Proto = cast<FunctionProtoType>(T); @@ -2083,8 +2198,19 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, return; } - for (const auto &Arg : Proto->param_types()) - mangleType(Context.getASTContext().getSignatureParameterType(Arg)); + assert(!FD || FD->getNumParams() == Proto->getNumParams()); + for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) { + const auto &ParamTy = Proto->getParamType(I); + mangleType(Context.getASTContext().getSignatureParameterType(ParamTy)); + + if (FD) { + if (auto *Attr = FD->getParamDecl(I)->getAttr<PassObjectSizeAttr>()) { + // Attr can only take 1 character, so we can hardcode the length below. + assert(Attr->getType() <= 9 && Attr->getType() >= 0); + Out << "U17pass_object_size" << Attr->getType(); + } + } + } FunctionTypeDepth.pop(saved); @@ -2325,7 +2451,7 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) { EltName = mangleAArch64VectorBase(cast<BuiltinType>(EltType)); std::string TypeName = - ("__" + EltName + "x" + llvm::utostr(T->getNumElements()) + "_t").str(); + ("__" + EltName + "x" + Twine(T->getNumElements()) + "_t").str(); Out << TypeName.length() << TypeName; } @@ -2392,7 +2518,6 @@ void CXXNameMangler::mangleType(const ObjCObjectType *T) { StringRef name = I->getName(); QualOS << name.size() << name; } - QualOS.flush(); Out << 'U' << QualStr.size() << QualStr; } @@ -2543,9 +2668,11 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) { void CXXNameMangler::mangleType(const AutoType *T) { QualType D = T->getDeducedType(); // <builtin-type> ::= Da # dependent auto - if (D.isNull()) + if (D.isNull()) { + assert(T->getKeyword() != AutoTypeKeyword::GNUAutoType && + "shouldn't need to mangle __auto_type!"); Out << (T->isDecltypeAuto() ? "Dc" : "Da"); - else + } else mangleType(D); } @@ -2556,6 +2683,13 @@ void CXXNameMangler::mangleType(const AtomicType *T) { mangleType(T->getValueType()); } +void CXXNameMangler::mangleType(const PipeType *T) { + // Pipe type mangling rules are described in SPIR 2.0 specification + // A.1 Data types and A.3 Summary of changes + // <type> ::= 8ocl_pipe + Out << "8ocl_pipe"; +} + void CXXNameMangler::mangleIntegerLiteral(QualType T, const llvm::APSInt &Value) { // <expr-primary> ::= L <type> <value number> E # integer literal @@ -2699,7 +2833,9 @@ recurse: case Expr::ParenListExprClass: case Expr::LambdaExprClass: case Expr::MSPropertyRefExprClass: + case Expr::MSPropertySubscriptExprClass: case Expr::TypoExprClass: // This should no longer exist in the AST by now. + case Expr::OMPArraySectionExprClass: llvm_unreachable("unexpected statement kind"); // FIXME: invent manglings for all these. @@ -2908,7 +3044,7 @@ recurse: ME->isArrow(), ME->getQualifier(), nullptr, ME->getMemberName(), Arity); if (ME->hasExplicitTemplateArgs()) - mangleTemplateArgs(ME->getExplicitTemplateArgs()); + mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs()); break; } @@ -2920,7 +3056,7 @@ recurse: ME->getFirstQualifierFoundInScope(), ME->getMember(), Arity); if (ME->hasExplicitTemplateArgs()) - mangleTemplateArgs(ME->getExplicitTemplateArgs()); + mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs()); break; } @@ -2932,7 +3068,7 @@ recurse: // base-unresolved-name, where <template-args> are just tacked // onto the end. if (ULE->hasExplicitTemplateArgs()) - mangleTemplateArgs(ULE->getExplicitTemplateArgs()); + mangleTemplateArgs(ULE->getTemplateArgs(), ULE->getNumTemplateArgs()); break; } @@ -3254,7 +3390,7 @@ recurse: // base-unresolved-name, where <template-args> are just tacked // onto the end. if (DRE->hasExplicitTemplateArgs()) - mangleTemplateArgs(DRE->getExplicitTemplateArgs()); + mangleTemplateArgs(DRE->getTemplateArgs(), DRE->getNumTemplateArgs()); break; } @@ -3350,8 +3486,17 @@ recurse: break; case Expr::SizeOfPackExprClass: { + auto *SPE = cast<SizeOfPackExpr>(E); + if (SPE->isPartiallySubstituted()) { + Out << "sP"; + for (const auto &A : SPE->getPartialArguments()) + mangleTemplateArg(A); + Out << "E"; + break; + } + Out << "sZ"; - const NamedDecl *Pack = cast<SizeOfPackExpr>(E)->getPack(); + const NamedDecl *Pack = SPE->getPack(); if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack)) mangleTemplateParameter(TTP->getIndex()); else if (const NonTypeTemplateParmDecl *NTTP @@ -3394,6 +3539,18 @@ recurse: case Expr::CXXThisExprClass: Out << "fpT"; break; + + case Expr::CoawaitExprClass: + // FIXME: Propose a non-vendor mangling. + Out << "v18co_await"; + mangleExpression(cast<CoawaitExpr>(E)->getOperand()); + break; + + case Expr::CoyieldExprClass: + // FIXME: Propose a non-vendor mangling. + Out << "v18co_yield"; + mangleExpression(cast<CoawaitExpr>(E)->getOperand()); + break; } } @@ -3501,12 +3658,12 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { } } -void CXXNameMangler::mangleTemplateArgs( - const ASTTemplateArgumentListInfo &TemplateArgs) { +void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs, + unsigned NumTemplateArgs) { // <template-args> ::= I <template-arg>+ E Out << 'I'; - for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i) - mangleTemplateArg(TemplateArgs.getTemplateArgs()[i].getArgument()); + for (unsigned i = 0; i != NumTemplateArgs; ++i) + mangleTemplateArg(TemplateArgs[i].getArgument()); Out << 'E'; } @@ -4085,21 +4242,6 @@ void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) { mangleCXXRTTIName(Ty, Out); } -void ItaniumMangleContextImpl::mangleCXXVTableBitSet(const CXXRecordDecl *RD, - raw_ostream &Out) { - if (!RD->isExternallyVisible()) { - // This part of the identifier needs to be unique across all translation - // units in the linked program. The scheme fails if multiple translation - // units are compiled using the same relative source file path, or if - // multiple translation units are built from the same source file. - SourceManager &SM = getASTContext().getSourceManager(); - Out << "[" << SM.getFileEntryForID(SM.getMainFileID())->getName() << "]"; - } - - CXXNameMangler Mangler(*this, Out); - Mangler.mangleType(QualType(RD->getTypeForDecl(), 0)); -} - void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) { llvm_unreachable("Can't mangle string literals"); } @@ -4108,4 +4250,3 @@ 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 1a061c4..014338f 100644 --- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp @@ -206,7 +206,6 @@ void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, SmallString<64> Buffer; llvm::raw_svector_ostream Out(Buffer); mangleCXXCtor(CD, CT, Out); - Out.flush(); mangleFunctionBlock(*this, Buffer, BD, ResStream); } @@ -216,7 +215,6 @@ void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, SmallString<64> Buffer; llvm::raw_svector_ostream Out(Buffer); mangleCXXDtor(DD, DT, Out); - Out.flush(); mangleFunctionBlock(*this, Buffer, BD, ResStream); } @@ -253,7 +251,6 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, } } } - Stream.flush(); mangleFunctionBlock(*this, Buffer, BD, Out); } diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp index aba6796..6ba31cc 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp @@ -70,6 +70,11 @@ class MicrosoftCXXABI : public CXXABI { llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *> CtorToDefaultArgExpr; + llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *> + UnnamedTagDeclToDeclaratorDecl; + llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *> + UnnamedTagDeclToTypedefNameDecl; + public: MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } @@ -84,17 +89,7 @@ public: } bool isNearlyEmpty(const CXXRecordDecl *RD) const override { - // FIXME: Audit the corners - if (!RD->isDynamicClass()) - return false; - - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - - // In the Microsoft ABI, classes can have one or two vtable pointers. - CharUnits PointerSize = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); - return Layout.getNonVirtualSize() == PointerSize || - Layout.getNonVirtualSize() == PointerSize * 2; + llvm_unreachable("unapplicable to the MS ABI"); } void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, @@ -120,6 +115,34 @@ public: RecordToCopyCtor[RD] = CD; } + void addTypedefNameForUnnamedTagDecl(TagDecl *TD, + TypedefNameDecl *DD) override { + TD = TD->getCanonicalDecl(); + DD = cast<TypedefNameDecl>(DD->getCanonicalDecl()); + TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD]; + if (!I) + I = DD; + } + + TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override { + return UnnamedTagDeclToTypedefNameDecl.lookup( + const_cast<TagDecl *>(TD->getCanonicalDecl())); + } + + void addDeclaratorForUnnamedTagDecl(TagDecl *TD, + DeclaratorDecl *DD) override { + TD = TD->getCanonicalDecl(); + DD = cast<DeclaratorDecl>(DD->getCanonicalDecl()); + DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD]; + if (!I) + I = DD; + } + + DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override { + return UnnamedTagDeclToDeclaratorDecl.lookup( + const_cast<TagDecl *>(TD->getCanonicalDecl())); + } + MangleNumberingContext *createMangleNumberingContext() const override { return new MicrosoftNumberingContext(); } diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 48a8fa5..4a45f9e 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/JamCRC.h" using namespace clang; @@ -126,8 +127,6 @@ public: CXXCtorType CT, uint32_t Size, uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBIndex, raw_ostream &Out) override; - void mangleCXXCatchHandlerType(QualType T, uint32_t Flags, - 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, @@ -160,8 +159,6 @@ public: void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl, raw_ostream &Out) override; void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override; - void mangleCXXVTableBitSet(const CXXRecordDecl *RD, - raw_ostream &Out) override; bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { // Lambda closure types are already numbered. if (isLambda(ND)) @@ -179,7 +176,9 @@ public: // Anonymous tags are already numbered. if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) { - if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl()) + if (!Tag->hasNameForLinkage() && + !getASTContext().getDeclaratorForUnnamedTagDecl(Tag) && + !getASTContext().getTypedefNameForUnnamedTagDecl(Tag)) return false; } @@ -220,9 +219,12 @@ class MicrosoftCXXNameMangler { typedef llvm::SmallVector<std::string, 10> BackRefVec; BackRefVec NameBackReferences; - typedef llvm::DenseMap<void *, unsigned> ArgBackRefMap; + typedef llvm::DenseMap<const void *, unsigned> ArgBackRefMap; ArgBackRefMap TypeBackReferences; + typedef std::set<int> PassObjectSizeArgsSet; + PassObjectSizeArgsSet PassObjectSizeArgs; + ASTContext &getASTContext() const { return Context.getASTContext(); } // FIXME: If we add support for __ptr32/64 qualifiers, then we should push @@ -262,6 +264,9 @@ public: const CXXMethodDecl *MD, const MicrosoftVTableContext::MethodVFTableLocation &ML); void mangleNumber(int64_t Number); + void mangleTagTypeKind(TagTypeKind TK); + void mangleArtificalTagType(TagTypeKind TK, StringRef UnqualifiedName, + ArrayRef<StringRef> NestedNames = None); void mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM = QMM_Mangle); void mangleFunctionType(const FunctionType *T, @@ -289,6 +294,7 @@ private: void mangleObjCMethodName(const ObjCMethodDecl *MD); void mangleArgumentType(QualType T, SourceRange Range); + void manglePassObjectSizeArg(const PassObjectSizeAttr *POSA); // Declare manglers for every type class. #define ABSTRACT_TYPE(CLASS, PARENT) @@ -364,7 +370,8 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit() && D->getFormalLinkage() == InternalLinkage && - !isa<VarTemplateSpecializationDecl>(D)) + !isa<VarTemplateSpecializationDecl>(D) && + D->getIdentifier() != nullptr) return false; } @@ -390,14 +397,8 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD)); else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) mangleVariableEncoding(VD); - else { - // 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(); - } + else + llvm_unreachable("Tried to mangle unexpected NamedDecl!"); } void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD, @@ -420,7 +421,7 @@ void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD, // We would like to mangle all extern "C" functions using this additional // component but this would break compatibility with MSVC's behavior. // Instead, do this when we know that compatibility isn't important (in - // other words, when it is an overloaded extern "C" funciton). + // other words, when it is an overloaded extern "C" function). if (FD->isExternC() && FD->hasAttr<OverloadableAttr>()) Out << "$$J0"; @@ -695,8 +696,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // Function templates aren't considered for name back referencing. This // makes sense since function templates aren't likely to occur multiple // times in a symbol. - // FIXME: Test alias template mangling with MSVC 2013. - if (!isa<ClassTemplateDecl>(TD)) { + if (isa<FunctionTemplateDecl>(TD)) { mangleTemplateInstantiationName(TD, *TemplateArgs); Out << '@'; return; @@ -721,7 +721,6 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, llvm::raw_svector_ostream Stream(TemplateMangling); MicrosoftCXXNameMangler Extra(Context, Stream); Extra.mangleTemplateInstantiationName(TD, *TemplateArgs); - Stream.flush(); mangleSourceName(TemplateMangling); return; @@ -787,14 +786,21 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } llvm::SmallString<64> Name("<unnamed-type-"); - if (TD->hasDeclaratorForAnonDecl()) { - // Anonymous types with no tag or typedef get the name of their + if (DeclaratorDecl *DD = + Context.getASTContext().getDeclaratorForUnnamedTagDecl(TD)) { + // Anonymous types without a name for linkage purposes have their // declarator mangled in if they have one. - Name += TD->getDeclaratorForAnonDecl()->getName(); + Name += DD->getName(); + } else if (TypedefNameDecl *TND = + Context.getASTContext().getTypedefNameForUnnamedTagDecl( + TD)) { + // Anonymous types without a name for linkage purposes have their + // associate typedef mangled in if they have one. + Name += TND->getName(); } else { // Otherwise, number the types using a $S prefix. Name += "$S"; - Name += llvm::utostr(Context.getAnonymousStructId(TD)); + Name += llvm::utostr(Context.getAnonymousStructId(TD) + 1); } Name += ">"; mangleSourceName(Name.str()); @@ -1039,6 +1045,14 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, break; } + case OO_Coawait: { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this operator co_await yet"); + Diags.Report(Loc, DiagID); + break; + } + case OO_None: case NUM_OVERLOADED_OPERATORS: llvm_unreachable("Not an overloaded operator"); @@ -1071,8 +1085,10 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( // Templates have their own context for back references. ArgBackRefMap OuterArgsContext; BackRefVec OuterTemplateContext; + PassObjectSizeArgsSet OuterPassObjectSizeArgs; NameBackReferences.swap(OuterTemplateContext); TypeBackReferences.swap(OuterArgsContext); + PassObjectSizeArgs.swap(OuterPassObjectSizeArgs); mangleUnscopedTemplateName(TD); mangleTemplateArgs(TD, TemplateArgs); @@ -1080,6 +1096,7 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( // Restore the previous back reference contexts. NameBackReferences.swap(OuterTemplateContext); TypeBackReferences.swap(OuterArgsContext); + PassObjectSizeArgs.swap(OuterPassObjectSizeArgs); } void @@ -1121,12 +1138,6 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { UE = dyn_cast<CXXUuidofExpr>(E); if (UE) { - // This CXXUuidofExpr is mangled as-if it were actually a VarDecl from - // const __s_GUID _GUID_{lower case UUID with underscores} - StringRef Uuid = UE->getUuidAsStringRef(Context.getASTContext()); - std::string Name = "_GUID_" + Uuid.lower(); - std::replace(Name.begin(), Name.end(), '-', '_'); - // If we had to peek through an address-of operator, treat this like we are // dealing with a pointer type. Otherwise, treat it like a const reference. // @@ -1136,7 +1147,22 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { Out << "$E?"; else Out << "$1?"; - Out << Name << "@@3U__s_GUID@@B"; + + // This CXXUuidofExpr is mangled as-if it were actually a VarDecl from + // const __s_GUID _GUID_{lower case UUID with underscores} + StringRef Uuid = UE->getUuidAsStringRef(Context.getASTContext()); + std::string Name = "_GUID_" + Uuid.lower(); + std::replace(Name.begin(), Name.end(), '-', '_'); + + mangleSourceName(Name); + // Terminate the whole name with an '@'. + Out << '@'; + // It's a global variable. + Out << '3'; + // It's a struct called __s_GUID. + mangleArtificalTagType(TTK_Struct, "__s_GUID"); + // It's const. + Out << 'B'; return; } @@ -1210,12 +1236,13 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, QualType T = TA.getNullPtrType(); if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) { const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - if (MPT->isMemberFunctionPointerType() && isa<ClassTemplateDecl>(TD)) { + if (MPT->isMemberFunctionPointerType() && + !isa<FunctionTemplateDecl>(TD)) { mangleMemberFunctionPointer(RD, nullptr); return; } if (MPT->isMemberDataPointer()) { - if (isa<ClassTemplateDecl>(TD)) { + if (!isa<FunctionTemplateDecl>(TD)) { mangleMemberDataPointer(RD, nullptr); return; } @@ -1455,6 +1482,27 @@ void MicrosoftCXXNameMangler::mangleArgumentType(QualType T, } } +void MicrosoftCXXNameMangler::manglePassObjectSizeArg( + const PassObjectSizeAttr *POSA) { + int Type = POSA->getType(); + + auto Iter = PassObjectSizeArgs.insert(Type).first; + auto *TypePtr = (const void *)&*Iter; + ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); + + if (Found == TypeBackReferences.end()) { + mangleArtificalTagType(TTK_Enum, "__pass_object_size" + llvm::utostr(Type), + {"__clang"}); + + if (TypeBackReferences.size() < 10) { + size_t Size = TypeBackReferences.size(); + TypeBackReferences[TypePtr] = Size; + } + } else { + Out << Found->second; + } +} + void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM) { // Don't use the canonical types. MSVC includes things like 'const' on @@ -1546,29 +1594,72 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, // ::= _W # wchar_t // ::= _Z # __float80 (Digital Mars) switch (T->getKind()) { - case BuiltinType::Void: Out << 'X'; break; - case BuiltinType::SChar: Out << 'C'; break; - case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'D'; break; - case BuiltinType::UChar: Out << 'E'; break; - case BuiltinType::Short: Out << 'F'; break; - case BuiltinType::UShort: Out << 'G'; break; - case BuiltinType::Int: Out << 'H'; break; - case BuiltinType::UInt: Out << 'I'; break; - case BuiltinType::Long: Out << 'J'; break; - case BuiltinType::ULong: Out << 'K'; break; - case BuiltinType::Float: Out << 'M'; break; - case BuiltinType::Double: Out << 'N'; break; + case BuiltinType::Void: + Out << 'X'; + break; + case BuiltinType::SChar: + Out << 'C'; + break; + case BuiltinType::Char_U: + case BuiltinType::Char_S: + Out << 'D'; + break; + case BuiltinType::UChar: + Out << 'E'; + break; + case BuiltinType::Short: + Out << 'F'; + break; + case BuiltinType::UShort: + Out << 'G'; + break; + case BuiltinType::Int: + Out << 'H'; + break; + case BuiltinType::UInt: + Out << 'I'; + break; + case BuiltinType::Long: + Out << 'J'; + break; + case BuiltinType::ULong: + Out << 'K'; + break; + case BuiltinType::Float: + Out << 'M'; + break; + case BuiltinType::Double: + Out << 'N'; + break; // TODO: Determine size and mangle accordingly - case BuiltinType::LongDouble: Out << 'O'; break; - case BuiltinType::LongLong: Out << "_J"; break; - case BuiltinType::ULongLong: Out << "_K"; break; - case BuiltinType::Int128: Out << "_L"; break; - case BuiltinType::UInt128: Out << "_M"; break; - case BuiltinType::Bool: Out << "_N"; break; - case BuiltinType::Char16: Out << "_S"; break; - case BuiltinType::Char32: Out << "_U"; break; + case BuiltinType::LongDouble: + Out << 'O'; + break; + case BuiltinType::LongLong: + Out << "_J"; + break; + case BuiltinType::ULongLong: + Out << "_K"; + break; + case BuiltinType::Int128: + Out << "_L"; + break; + case BuiltinType::UInt128: + Out << "_M"; + break; + case BuiltinType::Bool: + Out << "_N"; + break; + case BuiltinType::Char16: + Out << "_S"; + break; + case BuiltinType::Char32: + Out << "_U"; + break; case BuiltinType::WChar_S: - case BuiltinType::WChar_U: Out << "_W"; break; + case BuiltinType::WChar_U: + Out << "_W"; + break; #define BUILTIN_TYPE(Id, SingletonId) #define PLACEHOLDER_TYPE(Id, SingletonId) \ @@ -1577,28 +1668,102 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, case BuiltinType::Dependent: llvm_unreachable("placeholder types shouldn't get to name mangling"); - case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break; - case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break; - case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break; + case BuiltinType::ObjCId: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "objc_object"); + break; + case BuiltinType::ObjCClass: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "objc_class"); + break; + case BuiltinType::ObjCSel: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "objc_selector"); + break; - case BuiltinType::OCLImage1d: Out << "PAUocl_image1d@@"; break; - case BuiltinType::OCLImage1dArray: Out << "PAUocl_image1darray@@"; break; - case BuiltinType::OCLImage1dBuffer: Out << "PAUocl_image1dbuffer@@"; break; - case BuiltinType::OCLImage2d: Out << "PAUocl_image2d@@"; break; - case BuiltinType::OCLImage2dArray: Out << "PAUocl_image2darray@@"; break; - case BuiltinType::OCLImage3d: Out << "PAUocl_image3d@@"; break; - case BuiltinType::OCLSampler: Out << "PAUocl_sampler@@"; break; - case BuiltinType::OCLEvent: Out << "PAUocl_event@@"; break; + case BuiltinType::OCLImage1d: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image1d"); + break; + case BuiltinType::OCLImage1dArray: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image1darray"); + break; + case BuiltinType::OCLImage1dBuffer: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image1dbuffer"); + break; + case BuiltinType::OCLImage2d: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image2d"); + break; + case BuiltinType::OCLImage2dArray: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image2darray"); + break; + case BuiltinType::OCLImage2dDepth: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image2ddepth"); + break; + case BuiltinType::OCLImage2dArrayDepth: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image2darraydepth"); + break; + case BuiltinType::OCLImage2dMSAA: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image2dmsaa"); + break; + case BuiltinType::OCLImage2dArrayMSAA: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image2darraymsaa"); + break; + case BuiltinType::OCLImage2dMSAADepth: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image2dmsaadepth"); + break; + case BuiltinType::OCLImage2dArrayMSAADepth: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image2darraymsaadepth"); + break; + case BuiltinType::OCLImage3d: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_image3d"); + break; + case BuiltinType::OCLSampler: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_sampler"); + break; + case BuiltinType::OCLEvent: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_event"); + break; + case BuiltinType::OCLClkEvent: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_clkevent"); + break; + case BuiltinType::OCLQueue: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_queue"); + break; + case BuiltinType::OCLNDRange: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_ndrange"); + break; + case BuiltinType::OCLReserveID: + Out << "PA"; + mangleArtificalTagType(TTK_Struct, "ocl_reserveid"); + break; - case BuiltinType::NullPtr: Out << "$$T"; break; + case BuiltinType::NullPtr: + Out << "$$T"; + break; case BuiltinType::Half: { DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this built-in %0 type yet"); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "cannot mangle this built-in %0 type yet"); Diags.Report(Range.getBegin(), DiagID) - << T->getName(Context.getASTContext().getPrintingPolicy()) - << Range; + << T->getName(Context.getASTContext().getPrintingPolicy()) << Range; break; } } @@ -1620,7 +1785,8 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, Qualifiers, } void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T, Qualifiers, SourceRange) { - llvm_unreachable("Can't mangle K&R function prototypes"); + Out << "$$A6"; + mangleFunctionType(T); } void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, @@ -1628,7 +1794,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, bool ForceThisQuals) { // <function-type> ::= <this-cvr-qualifiers> <calling-convention> // <return-type> <argument-list> <throw-spec> - const FunctionProtoType *Proto = cast<FunctionProtoType>(T); + const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(T); SourceRange Range; if (D) Range = D->getSourceRange(); @@ -1699,12 +1865,14 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, } Out << '@'; } else { - QualType ResultType = Proto->getReturnType(); + QualType ResultType = T->getReturnType(); if (const auto *AT = dyn_cast_or_null<AutoType>(ResultType->getContainedAutoType())) { Out << '?'; mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false); Out << '?'; + assert(AT->getKeyword() != AutoTypeKeyword::GNUAutoType && + "shouldn't need to mangle __auto_type!"); mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>"); Out << '@'; } else { @@ -1717,12 +1885,29 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // <argument-list> ::= X # void // ::= <type>+ @ // ::= <type>* Z # varargs - if (Proto->getNumParams() == 0 && !Proto->isVariadic()) { + if (!Proto) { + // Function types without prototypes can arise when mangling a function type + // within an overloadable function in C. We mangle these as the absence of + // any parameter types (not even an empty parameter list). + Out << '@'; + } else if (Proto->getNumParams() == 0 && !Proto->isVariadic()) { Out << 'X'; } else { // Happens for function pointer type arguments for example. - for (const QualType &Arg : Proto->param_types()) - mangleArgumentType(Arg, Range); + for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) { + mangleArgumentType(Proto->getParamType(I), Range); + // Mangle each pass_object_size parameter as if it's a paramater of enum + // type passed directly after the parameter with the pass_object_size + // attribute. The aforementioned enum's name is __pass_object_size, and we + // pretend it resides in a top-level namespace called __clang. + // + // FIXME: Is there a defined extension notation for the MS ABI, or is it + // necessary to just cross our fingers and hope this type+namespace + // combination doesn't conflict with anything? + if (D) + if (const auto *P = D->getParamDecl(I)->getAttr<PassObjectSizeAttr>()) + manglePassObjectSizeArg(P); + } // <builtin-type> ::= Z # ellipsis if (Proto->isVariadic()) Out << 'Z'; @@ -1851,16 +2036,8 @@ void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T, // <struct-type> ::= U <name> // <class-type> ::= V <name> // <enum-type> ::= W4 <name> -void MicrosoftCXXNameMangler::mangleType(const EnumType *T, Qualifiers, - SourceRange) { - mangleType(cast<TagType>(T)->getDecl()); -} -void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers, - SourceRange) { - mangleType(cast<TagType>(T)->getDecl()); -} -void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { - switch (TD->getTagKind()) { +void MicrosoftCXXNameMangler::mangleTagTypeKind(TagTypeKind TTK) { + switch (TTK) { case TTK_Union: Out << 'T'; break; @@ -1875,8 +2052,33 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { Out << "W4"; break; } +} +void MicrosoftCXXNameMangler::mangleType(const EnumType *T, Qualifiers, + SourceRange) { + mangleType(cast<TagType>(T)->getDecl()); +} +void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers, + SourceRange) { + mangleType(cast<TagType>(T)->getDecl()); +} +void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { + mangleTagTypeKind(TD->getTagKind()); mangleName(TD); } +void MicrosoftCXXNameMangler::mangleArtificalTagType( + TagTypeKind TK, StringRef UnqualifiedName, ArrayRef<StringRef> NestedNames) { + // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @ + mangleTagTypeKind(TK); + + // Always start with the unqualified name. + mangleSourceName(UnqualifiedName); + + for (auto I = NestedNames.rbegin(), E = NestedNames.rend(); I != E; ++I) + mangleSourceName(*I); + + // Terminate the whole name with an '@'. + Out << '@'; +} // <type> ::= <array-type> // <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> @@ -2011,7 +2213,8 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T, Qualifiers Quals, SourceRange Range) { QualType PointeeType = T->getPointeeType(); - Out << (Quals.hasVolatile() ? 'B' : 'A'); + assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!"); + Out << 'A'; manglePointerExtQualifiers(Quals, PointeeType); mangleType(PointeeType, Range); } @@ -2022,18 +2225,24 @@ void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T, void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T, Qualifiers Quals, SourceRange Range) { QualType PointeeType = T->getPointeeType(); - Out << (Quals.hasVolatile() ? "$$R" : "$$Q"); + assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!"); + Out << "$$Q"; manglePointerExtQualifiers(Quals, PointeeType); mangleType(PointeeType, Range); } void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers, SourceRange Range) { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this complex number type yet"); - Diags.Report(Range.getBegin(), DiagID) - << Range; + QualType ElementType = T->getElementType(); + + llvm::SmallString<64> TemplateMangling; + llvm::raw_svector_ostream Stream(TemplateMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + Stream << "?$"; + Extra.mangleSourceName("_Complex"); + Extra.mangleType(ElementType, Range, QMM_Escape); + + mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"}); } void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals, @@ -2043,46 +2252,44 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals, uint64_t Width = getASTContext().getTypeSize(T); // Pattern match exactly the typedefs in our intrinsic headers. Anything that // doesn't match the Intel types uses a custom mangling below. - bool IsBuiltin = true; + size_t OutSizeBefore = Out.tell(); llvm::Triple::ArchType AT = getASTContext().getTargetInfo().getTriple().getArch(); if (AT == llvm::Triple::x86 || AT == llvm::Triple::x86_64) { if (Width == 64 && ET->getKind() == BuiltinType::LongLong) { - Out << "T__m64"; + mangleArtificalTagType(TTK_Union, "__m64"); } else if (Width >= 128) { if (ET->getKind() == BuiltinType::Float) - Out << "T__m" << Width; + mangleArtificalTagType(TTK_Union, "__m" + llvm::utostr(Width)); else if (ET->getKind() == BuiltinType::LongLong) - Out << "T__m" << Width << 'i'; + mangleArtificalTagType(TTK_Union, "__m" + llvm::utostr(Width) + 'i'); else if (ET->getKind() == BuiltinType::Double) - Out << "U__m" << Width << 'd'; - else - IsBuiltin = false; - } else { - IsBuiltin = false; + mangleArtificalTagType(TTK_Struct, "__m" + llvm::utostr(Width) + 'd'); } - } else { - IsBuiltin = false; } + bool IsBuiltin = Out.tell() != OutSizeBefore; if (!IsBuiltin) { // The MS ABI doesn't have a special mangling for vector types, so we define // our own mangling to handle uses of __vector_size__ on user-specified // types, and for extensions like __v4sf. - Out << "T__clang_vec" << T->getNumElements() << '_'; - mangleType(ET, Quals, Range); - } - Out << "@@"; + llvm::SmallString<64> TemplateMangling; + llvm::raw_svector_ostream Stream(TemplateMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + Stream << "?$"; + Extra.mangleSourceName("__vector"); + Extra.mangleType(QualType(ET, 0), Range, QMM_Escape); + Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumElements()), + /*IsBoolean=*/false); + + mangleArtificalTagType(TTK_Union, TemplateMangling, {"__clang"}); + } } -void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, Qualifiers, - SourceRange Range) { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this extended vector type yet"); - Diags.Report(Range.getBegin(), DiagID) - << Range; +void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, + Qualifiers Quals, SourceRange Range) { + mangleType(static_cast<const VectorType *>(T), Quals, Range); } void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T, Qualifiers, SourceRange Range) { @@ -2096,7 +2303,7 @@ void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T, void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers, SourceRange) { // ObjC interfaces have structs underlying them. - Out << 'U'; + mangleTagTypeKind(TTK_Struct); mangleName(T->getDecl()); } @@ -2209,9 +2416,23 @@ void MicrosoftCXXNameMangler::mangleType(const AutoType *T, Qualifiers, void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers, SourceRange Range) { + QualType ValueType = T->getValueType(); + + llvm::SmallString<64> TemplateMangling; + llvm::raw_svector_ostream Stream(TemplateMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + Stream << "?$"; + Extra.mangleSourceName("_Atomic"); + Extra.mangleType(ValueType, Range, QMM_Escape); + + mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"}); +} + +void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers, + SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this C11 atomic type yet"); + "cannot mangle this OpenCL pipe type yet"); Diags.Report(Range.getBegin(), DiagID) << Range; } @@ -2408,15 +2629,6 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); } -void MicrosoftMangleContextImpl::mangleCXXCatchHandlerType(QualType T, - uint32_t Flags, - raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); - Mangler.getStream() << "llvm.eh.handlertype."; - Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); - Mangler.getStream() << '.' << Flags; -} - void MicrosoftMangleContextImpl::mangleCXXVirtualDisplacementMap( const CXXRecordDecl *SrcRD, const CXXRecordDecl *DstRD, raw_ostream &Out) { MicrosoftCXXNameMangler Mangler(*this, Out); @@ -2574,12 +2786,12 @@ void MicrosoftMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D, mangler.mangle(D); } -void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD, - unsigned, - raw_ostream &) { - unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this reference temporary yet"); - getDiags().Report(VD->getLocation(), DiagID); +void MicrosoftMangleContextImpl::mangleReferenceTemporary( + const VarDecl *VD, unsigned ManglingNumber, raw_ostream &Out) { + MicrosoftCXXNameMangler Mangler(*this, Out); + + Mangler.getStream() << "\01?$RT" << ManglingNumber << '@'; + Mangler.mangle(VD, ""); } void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable( @@ -2688,28 +2900,6 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, // 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); @@ -2725,22 +2915,19 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, }; // CRC all the bytes of the StringLiteral. + llvm::JamCRC JC; for (unsigned I = 0, E = SL->getByteLength(); I != E; ++I) - UpdateCRC(GetLittleEndianByte(I)); + JC.update(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); + JC.update('\x00'); // <encoded-crc>: The CRC is encoded utilizing the standard number mangling // scheme. - Mangler.mangleNumber(CRC); + Mangler.mangleNumber(JC.getCRC()); // <encoded-string>: The mangled name also contains the first 32 _characters_ // (including null-terminator bytes) of the StringLiteral. @@ -2790,21 +2977,6 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, Mangler.getStream() << '@'; } -void MicrosoftMangleContextImpl::mangleCXXVTableBitSet(const CXXRecordDecl *RD, - raw_ostream &Out) { - if (!RD->isExternallyVisible()) { - // This part of the identifier needs to be unique across all translation - // units in the linked program. The scheme fails if multiple translation - // units are compiled using the same relative source file path, or if - // multiple translation units are built from the same source file. - SourceManager &SM = getASTContext().getSourceManager(); - Out << "[" << SM.getFileEntryForID(SM.getMainFileID())->getName() << "]"; - } - - MicrosoftCXXNameMangler mangler(*this, Out); - mangler.mangleName(RD); -} - 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 c9264d5..c562dae 100644 --- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp @@ -450,9 +450,19 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { case BuiltinType::OCLImage1dBuffer: case BuiltinType::OCLImage2d: case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage2dDepth: + case BuiltinType::OCLImage2dArrayDepth: + case BuiltinType::OCLImage2dMSAA: + case BuiltinType::OCLImage2dArrayMSAA: + case BuiltinType::OCLImage2dMSAADepth: + case BuiltinType::OCLImage2dArrayMSAADepth: case BuiltinType::OCLImage3d: case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: + case BuiltinType::OCLClkEvent: + case BuiltinType::OCLQueue: + case BuiltinType::OCLNDRange: + case BuiltinType::OCLReserveID: case BuiltinType::BoundMember: case BuiltinType::Dependent: case BuiltinType::Overload: @@ -461,6 +471,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { case BuiltinType::Half: case BuiltinType::PseudoObject: case BuiltinType::BuiltinFn: + case BuiltinType::OMPArraySection: break; } diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index 97425d0..d2370c8 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -318,7 +318,12 @@ NestedNameSpecifier::print(raw_ostream &OS, OS << "::"; } -void NestedNameSpecifier::dump(const LangOptions &LO) { +void NestedNameSpecifier::dump(const LangOptions &LO) const { + print(llvm::errs(), PrintingPolicy(LO)); +} + +void NestedNameSpecifier::dump() const { + LangOptions LO; print(llvm::errs(), PrintingPolicy(LO)); } diff --git a/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp new file mode 100644 index 0000000..1ef43f7 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp @@ -0,0 +1,417 @@ +//===--- OpenMPClause.cpp - Classes for OpenMP clauses --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the subclesses of Stmt class declared in OpenMPClause.h +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/OpenMPClause.h" + +#include "clang/AST/ASTContext.h" + +using namespace clang; + +OMPClause::child_range OMPClause::children() { + switch (getClauseKind()) { + default: + break; +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_##Name: \ + return static_cast<Class *>(this)->children(); +#include "clang/Basic/OpenMPKinds.def" + } + llvm_unreachable("unknown OMPClause"); +} + +void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), varlist_end()); +} + +OMPPrivateClause * +OMPPrivateClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL) { + // Allocate space for private variables and initializer expressions. + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * VL.size())); + OMPPrivateClause *Clause = + new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setPrivateCopies(PrivateVL); + return Clause; +} + +OMPPrivateClause *OMPPrivateClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * N)); + return new (Mem) OMPPrivateClause(N); +} + +void OMPFirstprivateClause::setPrivateCopies(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), varlist_end()); +} + +void OMPFirstprivateClause::setInits(ArrayRef<Expr *> VL) { + assert(VL.size() == varlist_size() && + "Number of inits is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), getPrivateCopies().end()); +} + +OMPFirstprivateClause * +OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL, + ArrayRef<Expr *> InitVL) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(3 * VL.size())); + OMPFirstprivateClause *Clause = + new (Mem) OMPFirstprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setPrivateCopies(PrivateVL); + Clause->setInits(InitVL); + return Clause; +} + +OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(3 * N)); + return new (Mem) OMPFirstprivateClause(N); +} + +void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) { + assert(PrivateCopies.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end()); +} + +void OMPLastprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { + assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " + "not the same as the " + "preallocated buffer"); + std::copy(SrcExprs.begin(), SrcExprs.end(), getPrivateCopies().end()); +} + +void OMPLastprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { + assert(DstExprs.size() == varlist_size() && "Number of destination " + "expressions is not the same as " + "the preallocated buffer"); + std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); +} + +void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { + assert(AssignmentOps.size() == varlist_size() && + "Number of assignment expressions is not the same as the preallocated " + "buffer"); + std::copy(AssignmentOps.begin(), AssignmentOps.end(), + getDestinationExprs().end()); +} + +OMPLastprivateClause *OMPLastprivateClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, + ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size())); + OMPLastprivateClause *Clause = + new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setSourceExprs(SrcExprs); + Clause->setDestinationExprs(DstExprs); + Clause->setAssignmentOps(AssignmentOps); + return Clause; +} + +OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * 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(totalSizeToAlloc<Expr *>(VL.size())); + OMPSharedClause *Clause = + new (Mem) OMPSharedClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C, unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); + return new (Mem) OMPSharedClause(N); +} + +void OMPLinearClause::setPrivates(ArrayRef<Expr *> PL) { + assert(PL.size() == varlist_size() && + "Number of privates is not the same as the preallocated buffer"); + std::copy(PL.begin(), PL.end(), varlist_end()); +} + +void OMPLinearClause::setInits(ArrayRef<Expr *> IL) { + assert(IL.size() == varlist_size() && + "Number of inits is not the same as the preallocated buffer"); + std::copy(IL.begin(), IL.end(), getPrivates().end()); +} + +void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) { + assert(UL.size() == varlist_size() && + "Number of updates is not the same as the preallocated buffer"); + std::copy(UL.begin(), UL.end(), getInits().end()); +} + +void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) { + assert(FL.size() == varlist_size() && + "Number of final updates is not the same as the preallocated buffer"); + std::copy(FL.begin(), FL.end(), getUpdates().end()); +} + +OMPLinearClause *OMPLinearClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, + ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep) { + // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions + // (Step and CalcStep). + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size() + 2)); + OMPLinearClause *Clause = new (Mem) OMPLinearClause( + StartLoc, LParenLoc, Modifier, ModifierLoc, ColonLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setPrivates(PL); + Clause->setInits(IL); + // Fill update and final expressions with zeroes, they are provided later, + // after the directive construction. + std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(), + nullptr); + std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(), + nullptr); + Clause->setStep(Step); + Clause->setCalcStep(CalcStep); + return Clause; +} + +OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C, + unsigned NumVars) { + // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions + // (Step and CalcStep). + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * NumVars + 2)); + 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(totalSizeToAlloc<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(totalSizeToAlloc<Expr *>(NumVars + 1)); + return new (Mem) OMPAlignedClause(NumVars); +} + +void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { + assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " + "not the same as the " + "preallocated buffer"); + std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end()); +} + +void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { + assert(DstExprs.size() == varlist_size() && "Number of destination " + "expressions is not the same as " + "the preallocated buffer"); + std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); +} + +void OMPCopyinClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { + assert(AssignmentOps.size() == varlist_size() && + "Number of assignment expressions is not the same as the preallocated " + "buffer"); + std::copy(AssignmentOps.begin(), AssignmentOps.end(), + getDestinationExprs().end()); +} + +OMPCopyinClause *OMPCopyinClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, + ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * VL.size())); + OMPCopyinClause *Clause = + new (Mem) OMPCopyinClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setSourceExprs(SrcExprs); + Clause->setDestinationExprs(DstExprs); + Clause->setAssignmentOps(AssignmentOps); + return Clause; +} + +OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C, unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * N)); + return new (Mem) OMPCopyinClause(N); +} + +void OMPCopyprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { + assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " + "not the same as the " + "preallocated buffer"); + std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end()); +} + +void OMPCopyprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { + assert(DstExprs.size() == varlist_size() && "Number of destination " + "expressions is not the same as " + "the preallocated buffer"); + std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); +} + +void OMPCopyprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { + assert(AssignmentOps.size() == varlist_size() && + "Number of assignment expressions is not the same as the preallocated " + "buffer"); + std::copy(AssignmentOps.begin(), AssignmentOps.end(), + getDestinationExprs().end()); +} + +OMPCopyprivateClause *OMPCopyprivateClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, + ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * VL.size())); + OMPCopyprivateClause *Clause = + new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setSourceExprs(SrcExprs); + Clause->setDestinationExprs(DstExprs); + Clause->setAssignmentOps(AssignmentOps); + return Clause; +} + +OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * N)); + return new (Mem) OMPCopyprivateClause(N); +} + +void OMPReductionClause::setPrivates(ArrayRef<Expr *> Privates) { + assert(Privates.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(Privates.begin(), Privates.end(), varlist_end()); +} + +void OMPReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) { + assert( + LHSExprs.size() == varlist_size() && + "Number of LHS expressions is not the same as the preallocated buffer"); + std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end()); +} + +void OMPReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) { + assert( + RHSExprs.size() == varlist_size() && + "Number of RHS expressions is not the same as the preallocated buffer"); + std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end()); +} + +void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) { + assert(ReductionOps.size() == varlist_size() && "Number of reduction " + "expressions is not the same " + "as the preallocated buffer"); + std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end()); +} + +OMPReductionClause *OMPReductionClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, + ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs, + ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size())); + OMPReductionClause *Clause = new (Mem) OMPReductionClause( + StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo); + Clause->setVarRefs(VL); + Clause->setPrivates(Privates); + Clause->setLHSExprs(LHSExprs); + Clause->setRHSExprs(RHSExprs); + Clause->setReductionOps(ReductionOps); + return Clause; +} + +OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * 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(totalSizeToAlloc<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(totalSizeToAlloc<Expr *>(N)); + return new (Mem) OMPFlushClause(N); +} + +OMPDependClause * +OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + OpenMPDependClauseKind DepKind, SourceLocation DepLoc, + SourceLocation ColonLoc, ArrayRef<Expr *> VL) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); + OMPDependClause *Clause = + new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setDependencyKind(DepKind); + Clause->setDependencyLoc(DepLoc); + Clause->setColonLoc(ColonLoc); + return Clause; +} + +OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); + return new (Mem) OMPDependClause(N); +} + +OMPMapClause *OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, + OpenMPMapClauseKind TypeModifier, + OpenMPMapClauseKind Type, + SourceLocation TypeLoc) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); + OMPMapClause *Clause = new (Mem) OMPMapClause( + TypeModifier, Type, TypeLoc, StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setMapTypeModifier(TypeModifier); + Clause->setMapType(Type); + Clause->setMapLoc(TypeLoc); + return Clause; +} + +OMPMapClause *OMPMapClause::CreateEmpty(const ASTContext &C, unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); + return new (Mem) OMPMapClause(N); +} diff --git a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp index 24b129a..8317f76 100644 --- a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp @@ -15,6 +15,7 @@ #include "clang/AST/CommentLexer.h" #include "clang/AST/CommentParser.h" #include "clang/AST/CommentSema.h" +#include "clang/Basic/CharInfo.h" #include "llvm/ADT/STLExtras.h" using namespace clang; @@ -62,12 +63,53 @@ std::pair<RawComment::CommentKind, bool> getCommentKind(StringRef Comment, bool mergedCommentIsTrailingComment(StringRef Comment) { return (Comment.size() > 3) && (Comment[3] == '<'); } + +/// Returns true if R1 and R2 both have valid locations that start on the same +/// column. +bool commentsStartOnSameColumn(const SourceManager &SM, const RawComment &R1, + const RawComment &R2) { + SourceLocation L1 = R1.getLocStart(); + SourceLocation L2 = R2.getLocStart(); + bool Invalid = false; + unsigned C1 = SM.getPresumedColumnNumber(L1, &Invalid); + if (!Invalid) { + unsigned C2 = SM.getPresumedColumnNumber(L2, &Invalid); + return !Invalid && (C1 == C2); + } + return false; +} } // unnamed namespace +/// \brief Determines whether there is only whitespace in `Buffer` between `P` +/// and the previous line. +/// \param Buffer The buffer to search in. +/// \param P The offset from the beginning of `Buffer` to start from. +/// \return true if all of the characters in `Buffer` ranging from the closest +/// line-ending character before `P` (or the beginning of `Buffer`) to `P - 1` +/// are whitespace. +static bool onlyWhitespaceOnLineBefore(const char *Buffer, unsigned P) { + // Search backwards until we see linefeed or carriage return. + for (unsigned I = P; I != 0; --I) { + char C = Buffer[I - 1]; + if (isVerticalWhitespace(C)) + return true; + if (!isHorizontalWhitespace(C)) + return false; + } + // We hit the beginning of the buffer. + return true; +} + +/// Returns whether `K` is an ordinary comment kind. +static bool isOrdinaryKind(RawComment::CommentKind K) { + return (K == RawComment::RCK_OrdinaryBCPL) || + (K == RawComment::RCK_OrdinaryC); +} + RawComment::RawComment(const SourceManager &SourceMgr, SourceRange SR, bool Merged, bool ParseAllComments) : Range(SR), RawTextValid(false), BriefTextValid(false), - IsAttached(false), IsAlmostTrailingComment(false), + IsAttached(false), IsTrailingComment(false), IsAlmostTrailingComment(false), ParseAllComments(ParseAllComments) { // Extract raw comment text, if possible. if (SR.getBegin() == SR.getEnd() || getRawText(SourceMgr).empty()) { @@ -75,17 +117,34 @@ RawComment::RawComment(const SourceManager &SourceMgr, SourceRange SR, return; } + // Guess comment kind. + std::pair<CommentKind, bool> K = getCommentKind(RawText, ParseAllComments); + + // Guess whether an ordinary comment is trailing. + if (ParseAllComments && isOrdinaryKind(K.first)) { + FileID BeginFileID; + unsigned BeginOffset; + std::tie(BeginFileID, BeginOffset) = + SourceMgr.getDecomposedLoc(Range.getBegin()); + if (BeginOffset != 0) { + bool Invalid = false; + const char *Buffer = + SourceMgr.getBufferData(BeginFileID, &Invalid).data(); + IsTrailingComment |= + (!Invalid && !onlyWhitespaceOnLineBefore(Buffer, BeginOffset)); + } + } + if (!Merged) { - // Guess comment kind. - std::pair<CommentKind, bool> K = getCommentKind(RawText, ParseAllComments); Kind = K.first; - IsTrailingComment = K.second; + IsTrailingComment |= K.second; IsAlmostTrailingComment = RawText.startswith("//<") || RawText.startswith("/*<"); } else { Kind = RCK_Merged; - IsTrailingComment = mergedCommentIsTrailingComment(RawText); + IsTrailingComment = + IsTrailingComment || mergedCommentIsTrailingComment(RawText); } } @@ -239,9 +298,22 @@ void RawCommentList::addComment(const RawComment &RC, const RawComment &C2 = RC; // Merge comments only if there is only whitespace between them. - // Can't merge trailing and non-trailing comments. + // Can't merge trailing and non-trailing comments unless the second is + // non-trailing ordinary in the same column, as in the case: + // int x; // documents x + // // more text + // versus: + // int x; // documents x + // int y; // documents y + // or: + // int x; // documents x + // // documents y + // int y; // Merge comments if they are on same or consecutive lines. - if (C1.isTrailingComment() == C2.isTrailingComment() && + if ((C1.isTrailingComment() == C2.isTrailingComment() || + (C1.isTrailingComment() && !C2.isTrailingComment() && + isOrdinaryKind(C2.getKind()) && + commentsStartOnSameColumn(SourceMgr, C1, C2))) && onlyWhitespaceBetween(SourceMgr, C1.getLocEnd(), C2.getLocStart(), /*MaxNewlinesAllowed=*/1)) { SourceRange MergedRange(C1.getLocStart(), C2.getLocEnd()); diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index de7bcb8..bc5ae0f 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -18,7 +18,6 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" @@ -565,7 +564,7 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD, typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy; -class RecordLayoutBuilder { +class ItaniumRecordLayoutBuilder { protected: // FIXME: Remove this and make the appropriate fields public. friend class clang::ASTContext; @@ -656,19 +655,18 @@ protected: /// Valid if UseExternalLayout is true. ExternalLayout External; - RecordLayoutBuilder(const ASTContext &Context, - EmptySubobjectMap *EmptySubobjects) - : Context(Context), EmptySubobjects(EmptySubobjects), Size(0), - Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()), - UseExternalLayout(false), InferAlignment(false), - Packed(false), IsUnion(false), IsMac68kAlign(false), IsMsStruct(false), - UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0), - MaxFieldAlignment(CharUnits::Zero()), - DataSize(0), NonVirtualSize(CharUnits::Zero()), - NonVirtualAlignment(CharUnits::One()), - PrimaryBase(nullptr), PrimaryBaseIsVirtual(false), - HasOwnVFPtr(false), - FirstNearlyEmptyVBase(nullptr) {} + ItaniumRecordLayoutBuilder(const ASTContext &Context, + EmptySubobjectMap *EmptySubobjects) + : Context(Context), EmptySubobjects(EmptySubobjects), Size(0), + Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()), + UseExternalLayout(false), InferAlignment(false), Packed(false), + IsUnion(false), IsMac68kAlign(false), IsMsStruct(false), + UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0), + MaxFieldAlignment(CharUnits::Zero()), DataSize(0), + NonVirtualSize(CharUnits::Zero()), + NonVirtualAlignment(CharUnits::One()), PrimaryBase(nullptr), + PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), + FirstNearlyEmptyVBase(nullptr) {} void Layout(const RecordDecl *D); void Layout(const CXXRecordDecl *D); @@ -782,13 +780,12 @@ protected: void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); } void setDataSize(uint64_t NewSize) { DataSize = NewSize; } - RecordLayoutBuilder(const RecordLayoutBuilder &) = delete; - void operator=(const RecordLayoutBuilder &) = delete; + ItaniumRecordLayoutBuilder(const ItaniumRecordLayoutBuilder &) = delete; + void operator=(const ItaniumRecordLayoutBuilder &) = delete; }; } // end anonymous namespace -void -RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) { +void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) { for (const auto &I : RD->bases()) { assert(!I.getType()->isDependentType() && "Cannot layout class with dependent bases."); @@ -817,7 +814,7 @@ RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) { } /// DeterminePrimaryBase - Determine the primary base of the given class. -void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { +void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { // If the class isn't dynamic, it won't have a primary base. if (!RD->isDynamicClass()) return; @@ -864,10 +861,8 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { assert(!PrimaryBase && "Should not get here with a primary base!"); } -BaseSubobjectInfo * -RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD, - bool IsVirtual, - BaseSubobjectInfo *Derived) { +BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo( + const CXXRecordDecl *RD, bool IsVirtual, BaseSubobjectInfo *Derived) { BaseSubobjectInfo *Info; if (IsVirtual) { @@ -943,7 +938,8 @@ RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD, return Info; } -void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) { +void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo( + const CXXRecordDecl *RD) { for (const auto &I : RD->bases()) { bool IsVirtual = I.isVirtual(); @@ -966,8 +962,8 @@ void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) { } } -void -RecordLayoutBuilder::EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign) { +void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment( + CharUnits UnpackedBaseAlign) { CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign; // The maximum field alignment overrides base align. @@ -984,8 +980,8 @@ RecordLayoutBuilder::EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign) { UpdateAlignment(BaseAlign, UnpackedBaseAlign); } -void -RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { +void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases( + const CXXRecordDecl *RD) { // Then, determine the primary base class. DeterminePrimaryBase(RD); @@ -1054,7 +1050,8 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { } } -void RecordLayoutBuilder::LayoutNonVirtualBase(const BaseSubobjectInfo *Base) { +void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase( + const BaseSubobjectInfo *Base) { // Layout the base. CharUnits Offset = LayoutBase(Base); @@ -1065,9 +1062,8 @@ void RecordLayoutBuilder::LayoutNonVirtualBase(const BaseSubobjectInfo *Base) { AddPrimaryVirtualBaseOffsets(Base, Offset); } -void -RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info, - CharUnits Offset) { +void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets( + const BaseSubobjectInfo *Info, CharUnits Offset) { // This base isn't interesting, it has no virtual bases. if (!Info->Class->getNumVBases()) return; @@ -1099,9 +1095,8 @@ RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info, } } -void -RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, - const CXXRecordDecl *MostDerivedClass) { +void ItaniumRecordLayoutBuilder::LayoutVirtualBases( + const CXXRecordDecl *RD, const CXXRecordDecl *MostDerivedClass) { const CXXRecordDecl *PrimaryBase; bool PrimaryBaseIsVirtual; @@ -1146,7 +1141,8 @@ RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, } } -void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) { +void ItaniumRecordLayoutBuilder::LayoutVirtualBase( + const BaseSubobjectInfo *Base) { assert(!Base->Derived && "Trying to lay out a primary virtual base!"); // Layout the base. @@ -1160,7 +1156,8 @@ void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) { AddPrimaryVirtualBaseOffsets(Base, Offset); } -CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { +CharUnits +ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base->Class); @@ -1229,7 +1226,7 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { return Offset; } -void RecordLayoutBuilder::InitializeLayout(const Decl *D) { +void ItaniumRecordLayoutBuilder::InitializeLayout(const Decl *D) { if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) { IsUnion = RD->isUnion(); IsMsStruct = RD->isMsStruct(Context); @@ -1277,7 +1274,7 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) { } } -void RecordLayoutBuilder::Layout(const RecordDecl *D) { +void ItaniumRecordLayoutBuilder::Layout(const RecordDecl *D) { InitializeLayout(D); LayoutFields(D); @@ -1286,7 +1283,7 @@ void RecordLayoutBuilder::Layout(const RecordDecl *D) { FinishLayout(D); } -void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { +void ItaniumRecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { InitializeLayout(RD); // Lay out the vtable and the non-virtual bases. @@ -1326,7 +1323,7 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { #endif } -void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { +void ItaniumRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { if (ObjCInterfaceDecl *SD = D->getSuperClass()) { const ASTRecordLayout &SL = Context.getASTObjCInterfaceLayout(SD); @@ -1349,7 +1346,7 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { FinishLayout(D); } -void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { +void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Layout each field, for now, just sequentially, respecting alignment. In // the future, this will need to be tweakable by targets. bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true); @@ -1370,10 +1367,10 @@ roundUpSizeToCharAlignment(uint64_t Size, return llvm::RoundUpToAlignment(Size, CharAlignment); } -void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, - uint64_t TypeSize, - bool FieldPacked, - const FieldDecl *D) { +void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, + uint64_t TypeSize, + bool FieldPacked, + const FieldDecl *D) { assert(Context.getLangOpts().CPlusPlus && "Can only have wide bit-fields in C++!"); @@ -1437,7 +1434,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, UpdateAlignment(TypeAlign); } -void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { +void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); uint64_t FieldSize = D->getBitWidthValue(Context); TypeInfo FieldInfo = Context.getTypeInfo(D->getType()); @@ -1555,7 +1552,8 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { FieldAlign = 1; // But, if there's an 'aligned' attribute on the field, honor that. - if (unsigned ExplicitFieldAlign = D->getMaxAlignment()) { + unsigned ExplicitFieldAlign = D->getMaxAlignment(); + if (ExplicitFieldAlign) { FieldAlign = std::max(FieldAlign, ExplicitFieldAlign); UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign); } @@ -1568,6 +1566,12 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits); } + // But, ms_struct just ignores all of that in unions, even explicit + // alignment attributes. + if (IsMsStruct && IsUnion) { + FieldAlign = UnpackedFieldAlign = 1; + } + // 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. @@ -1598,6 +1602,10 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { (AllowPadding && (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) { FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); + } else if (ExplicitFieldAlign) { + // TODO: figure it out what needs to be done on targets that don't honor + // bit-field type alignment like ARM APCS ABI. + FieldOffset = llvm::RoundUpToAlignment(FieldOffset, ExplicitFieldAlign); } // Repeat the computation for diagnostic purposes. @@ -1606,6 +1614,9 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, UnpackedFieldAlign); + else if (ExplicitFieldAlign) + UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, + ExplicitFieldAlign); } // If we're using external layout, give the external layout a chance @@ -1634,9 +1645,20 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // For unions, this is just a max operation, as usual. if (IsUnion) { - uint64_t RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, - Context); + // For ms_struct, allocate the entire storage unit --- unless this + // is a zero-width bitfield, in which case just use a size of 1. + uint64_t RoundedFieldSize; + if (IsMsStruct) { + RoundedFieldSize = + (FieldSize ? TypeSize : Context.getTargetInfo().getCharWidth()); + + // Otherwise, allocate just the number of bytes required to store + // the bitfield. + } else { + RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, Context); + } setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize)); + // For non-zero-width bitfields in ms_struct structs, allocate a new // storage unit if necessary. } else if (IsMsStruct && FieldSize) { @@ -1672,8 +1694,8 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { Context.toCharUnitsFromBits(UnpackedFieldAlign)); } -void RecordLayoutBuilder::LayoutField(const FieldDecl *D, - bool InsertExtraPadding) { +void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, + bool InsertExtraPadding) { if (D->isBitField()) { LayoutBitField(D); return; @@ -1800,7 +1822,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D, UpdateAlignment(FieldAlign, UnpackedFieldAlign); } -void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { +void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) { // In C++, records cannot be of size 0. if (Context.getLangOpts().CPlusPlus && getSizeInBits() == 0) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { @@ -1852,7 +1874,7 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { Diag(RD->getLocation(), diag::warn_padded_struct_size) << Context.getTypeDeclType(RD) << PadSize - << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not + << (InBits ? 1 : 0); // (byte|bit) } // Warn if we packed it unnecessarily. If the alignment is 1 byte don't @@ -1864,8 +1886,8 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { } } -void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment, - CharUnits UnpackedNewAlignment) { +void ItaniumRecordLayoutBuilder::UpdateAlignment( + CharUnits NewAlignment, CharUnits UnpackedNewAlignment) { // The alignment is not modified when using 'mac68k' alignment or when // we have an externally-supplied layout that also provides overall alignment. if (IsMac68kAlign || (UseExternalLayout && !InferAlignment)) @@ -1885,8 +1907,8 @@ void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment, } uint64_t -RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field, - uint64_t ComputedOffset) { +ItaniumRecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field, + uint64_t ComputedOffset) { uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field); if (InferAlignment && ExternalFieldOffset < ComputedOffset) { @@ -1914,12 +1936,9 @@ static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag) { } } -void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset, - uint64_t UnpaddedOffset, - uint64_t UnpackedOffset, - unsigned UnpackedAlign, - bool isPacked, - const FieldDecl *D) { +void ItaniumRecordLayoutBuilder::CheckFieldPadding( + uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset, + unsigned UnpackedAlign, bool isPacked, const FieldDecl *D) { // We let objc ivars without warning, objc interfaces generally are not used // for padding tricks. if (isa<ObjCIvarDecl>(D)) @@ -1945,14 +1964,14 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset, << getPaddingDiagFromTagKind(D->getParent()->getTagKind()) << Context.getTypeDeclType(D->getParent()) << PadSize - << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not + << (InBits ? 1 : 0) // (byte|bit) << D->getIdentifier(); else Diag(D->getLocation(), diag::warn_padded_struct_anon_field) << getPaddingDiagFromTagKind(D->getParent()->getTagKind()) << Context.getTypeDeclType(D->getParent()) << PadSize - << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not + << (InBits ? 1 : 0); // (byte|bit) } // Warn if we packed it unnecessarily. If the alignment is 1 byte don't @@ -2014,6 +2033,21 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, continue; } + if (Context.getLangOpts().CUDA) { + // While compiler may see key method in this TU, during CUDA + // compilation we should ignore methods that are not accessible + // on this side of compilation. + if (Context.getLangOpts().CUDAIsDevice) { + // In device mode ignore methods without __device__ attribute. + if (!MD->hasAttr<CUDADeviceAttr>()) + continue; + } else { + // In host mode ignore __device__-only methods. + if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>()) + continue; + } + } + // If the key function is dllimport but the class isn't, then the class has // no key function. The DLL that exports the key function won't export the // vtable in this case. @@ -2027,8 +2061,8 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, return nullptr; } -DiagnosticBuilder -RecordLayoutBuilder::Diag(SourceLocation Loc, unsigned DiagID) { +DiagnosticBuilder ItaniumRecordLayoutBuilder::Diag(SourceLocation Loc, + unsigned DiagID) { return Context.getDiagnostics().Report(Loc, DiagID); } @@ -2074,8 +2108,8 @@ static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) { llvm_unreachable("bad tail-padding use kind"); } -static bool isMsLayout(const RecordDecl* D) { - return D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft(); +static bool isMsLayout(const ASTContext &Context) { + return Context.getTargetInfo().getCXXABI().isMicrosoft(); } // This section contains an implementation of struct layout that is, up to the @@ -2656,13 +2690,20 @@ void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) { // 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. + // Push back the vbptr, but increase the size of the object and push back + // regular fields by the offset only if not using external record layout. + if (HasVBPtr) + VBPtrOffset += Offset; + + if (UseExternalLayout) + return; + Size += Offset; + + // If we're using an external layout, the fields offsets have already + // accounted for this adjustment. for (uint64_t &FieldOffset : FieldOffsets) FieldOffset += Context.toBits(Offset); - if (HasVBPtr) - VBPtrOffset += Offset; for (BaseOffsetsMapTy::value_type &Base : Bases) Base.second += Offset; } @@ -2840,32 +2881,6 @@ void MicrosoftRecordLayoutBuilder::computeVtorDispSet( } } -/// \brief Get or compute information about the layout of the specified record -/// (struct/union/class), which indicates its size and field position -/// information. -const ASTRecordLayout * -ASTContext::BuildMicrosoftASTRecordLayout(const RecordDecl *D) const { - MicrosoftRecordLayoutBuilder Builder(*this); - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - Builder.cxxLayout(RD); - return new (*this) ASTRecordLayout( - *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.RequiredAlignment, - Builder.Size, Builder.FieldOffsets.data(), Builder.FieldOffsets.size()); - } -} - /// getASTRecordLayout - Get or compute information about the layout of the /// specified record (struct/union/class), which indicates its size and field /// position information. @@ -2892,54 +2907,63 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { const ASTRecordLayout *NewEntry = nullptr; - if (isMsLayout(D)) { - NewEntry = BuildMicrosoftASTRecordLayout(D); - } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - EmptySubobjectMap EmptySubobjects(*this, RD); - RecordLayoutBuilder Builder(*this, &EmptySubobjects); - Builder.Layout(RD); - - // In certain situations, we are allowed to lay out objects in the - // tail-padding of base classes. This is ABI-dependent. - // FIXME: this should be stored in the record layout. - bool skipTailPadding = - mustSkipTailPadding(getTargetInfo().getCXXABI(), cast<CXXRecordDecl>(D)); - - // FIXME: This should be done in FinalizeLayout. - CharUnits DataSize = - skipTailPadding ? Builder.getSize() : Builder.getDataSize(); - CharUnits NonVirtualSize = - skipTailPadding ? DataSize : Builder.NonVirtualSize; - NewEntry = - new (*this) ASTRecordLayout(*this, Builder.getSize(), - Builder.Alignment, - /*RequiredAlignment : used by MS-ABI)*/ - Builder.Alignment, - Builder.HasOwnVFPtr, - RD->isDynamicClass(), - CharUnits::fromQuantity(-1), - DataSize, - Builder.FieldOffsets.data(), - Builder.FieldOffsets.size(), - NonVirtualSize, - Builder.NonVirtualAlignment, - EmptySubobjects.SizeOfLargestEmptySubobject, - Builder.PrimaryBase, - Builder.PrimaryBaseIsVirtual, - nullptr, false, false, - Builder.Bases, Builder.VBases); + if (isMsLayout(*this)) { + MicrosoftRecordLayoutBuilder Builder(*this); + if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { + Builder.cxxLayout(RD); + NewEntry = new (*this) ASTRecordLayout( + *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); + NewEntry = new (*this) ASTRecordLayout( + *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment, + Builder.Size, Builder.FieldOffsets.data(), + Builder.FieldOffsets.size()); + } } else { - 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()); + if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { + EmptySubobjectMap EmptySubobjects(*this, RD); + ItaniumRecordLayoutBuilder Builder(*this, &EmptySubobjects); + Builder.Layout(RD); + + // In certain situations, we are allowed to lay out objects in the + // tail-padding of base classes. This is ABI-dependent. + // FIXME: this should be stored in the record layout. + bool skipTailPadding = + mustSkipTailPadding(getTargetInfo().getCXXABI(), RD); + + // FIXME: This should be done in FinalizeLayout. + CharUnits DataSize = + skipTailPadding ? Builder.getSize() : Builder.getDataSize(); + CharUnits NonVirtualSize = + skipTailPadding ? DataSize : Builder.NonVirtualSize; + NewEntry = new (*this) ASTRecordLayout( + *this, Builder.getSize(), Builder.Alignment, + /*RequiredAlignment : used by MS-ABI)*/ + Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(), + CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets.data(), + Builder.FieldOffsets.size(), NonVirtualSize, + Builder.NonVirtualAlignment, + EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase, + Builder.PrimaryBaseIsVirtual, nullptr, false, false, Builder.Bases, + Builder.VBases); + } else { + ItaniumRecordLayoutBuilder 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()); + } } ASTRecordLayouts[D] = NewEntry; @@ -3049,7 +3073,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, return getObjCLayout(D, nullptr); } - RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr); + ItaniumRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr); Builder.Layout(D); const ASTRecordLayout *NewEntry = @@ -3068,148 +3092,193 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel) { - OS << llvm::format("%4" PRId64 " | ", (int64_t)Offset.getQuantity()); + OS << llvm::format("%10" PRId64 " | ", (int64_t)Offset.getQuantity()); + OS.indent(IndentLevel * 2); +} + +static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset, + unsigned Begin, unsigned Width, + unsigned IndentLevel) { + llvm::SmallString<10> Buffer; + { + llvm::raw_svector_ostream BufferOS(Buffer); + BufferOS << Offset.getQuantity() << ':'; + if (Width == 0) { + BufferOS << '-'; + } else { + BufferOS << Begin << '-' << (Begin + Width - 1); + } + } + + OS << llvm::right_justify(Buffer, 10) << " | "; OS.indent(IndentLevel * 2); } static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel) { - OS << " | "; + OS << " | "; OS.indent(IndentLevel * 2); } -static void DumpCXXRecordLayout(raw_ostream &OS, - const CXXRecordDecl *RD, const ASTContext &C, - CharUnits Offset, - unsigned IndentLevel, - const char* Description, - bool IncludeVirtualBases) { +static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, + const ASTContext &C, + CharUnits Offset, + unsigned IndentLevel, + const char* Description, + bool PrintSizeInfo, + bool IncludeVirtualBases) { const ASTRecordLayout &Layout = C.getASTRecordLayout(RD); + auto CXXRD = dyn_cast<CXXRecordDecl>(RD); PrintOffset(OS, Offset, IndentLevel); - OS << C.getTypeDeclType(const_cast<CXXRecordDecl *>(RD)).getAsString(); + OS << C.getTypeDeclType(const_cast<RecordDecl*>(RD)).getAsString(); if (Description) OS << ' ' << Description; - if (RD->isEmpty()) + if (CXXRD && CXXRD->isEmpty()) OS << " (empty)"; OS << '\n'; IndentLevel++; - const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - bool HasOwnVFPtr = Layout.hasOwnVFPtr(); - bool HasOwnVBPtr = Layout.hasOwnVBPtr(); - - // Vtable pointer. - if (RD->isDynamicClass() && !PrimaryBase && !isMsLayout(RD)) { - PrintOffset(OS, Offset, IndentLevel); - OS << '(' << *RD << " vtable pointer)\n"; - } else if (HasOwnVFPtr) { - PrintOffset(OS, Offset, IndentLevel); - // vfptr (for Microsoft C++ ABI) - OS << '(' << *RD << " vftable pointer)\n"; - } - - // Collect nvbases. - SmallVector<const CXXRecordDecl *, 4> Bases; - for (const CXXBaseSpecifier &Base : RD->bases()) { - assert(!Base.getType()->isDependentType() && - "Cannot layout class with dependent bases."); - if (!Base.isVirtual()) - Bases.push_back(Base.getType()->getAsCXXRecordDecl()); - } + // Dump bases. + if (CXXRD) { + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + bool HasOwnVFPtr = Layout.hasOwnVFPtr(); + bool HasOwnVBPtr = Layout.hasOwnVBPtr(); + + // Vtable pointer. + if (CXXRD->isDynamicClass() && !PrimaryBase && !isMsLayout(C)) { + PrintOffset(OS, Offset, IndentLevel); + OS << '(' << *RD << " vtable pointer)\n"; + } else if (HasOwnVFPtr) { + PrintOffset(OS, Offset, IndentLevel); + // vfptr (for Microsoft C++ ABI) + OS << '(' << *RD << " vftable pointer)\n"; + } - // Sort nvbases by offset. - std::stable_sort(Bases.begin(), Bases.end(), - [&](const CXXRecordDecl *L, const CXXRecordDecl *R) { - return Layout.getBaseClassOffset(L) < Layout.getBaseClassOffset(R); - }); + // Collect nvbases. + SmallVector<const CXXRecordDecl *, 4> Bases; + for (const CXXBaseSpecifier &Base : CXXRD->bases()) { + assert(!Base.getType()->isDependentType() && + "Cannot layout class with dependent bases."); + if (!Base.isVirtual()) + Bases.push_back(Base.getType()->getAsCXXRecordDecl()); + } - // 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); - } + // 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); + DumpRecordLayout(OS, Base, C, BaseOffset, IndentLevel, + Base == PrimaryBase ? "(primary base)" : "(base)", + /*PrintSizeInfo=*/false, + /*IncludeVirtualBases=*/false); + } - // vbptr (for Microsoft C++ ABI) - if (HasOwnVBPtr) { - PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel); - OS << '(' << *RD << " vbtable pointer)\n"; + // vbptr (for Microsoft C++ ABI) + if (HasOwnVBPtr) { + PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel); + OS << '(' << *RD << " vbtable pointer)\n"; + } } // Dump fields. uint64_t FieldNo = 0; - for (CXXRecordDecl::field_iterator I = RD->field_begin(), + for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++FieldNo) { const FieldDecl &Field = **I; - CharUnits FieldOffset = Offset + - C.toCharUnitsFromBits(Layout.getFieldOffset(FieldNo)); - - if (const CXXRecordDecl *D = Field.getType()->getAsCXXRecordDecl()) { - DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel, - Field.getName().data(), - /*IncludeVirtualBases=*/true); + uint64_t LocalFieldOffsetInBits = Layout.getFieldOffset(FieldNo); + CharUnits FieldOffset = + Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits); + + // Recursively dump fields of record type. + if (auto RT = Field.getType()->getAs<RecordType>()) { + DumpRecordLayout(OS, RT->getDecl(), C, FieldOffset, IndentLevel, + Field.getName().data(), + /*PrintSizeInfo=*/false, + /*IncludeVirtualBases=*/true); continue; } - PrintOffset(OS, FieldOffset, IndentLevel); + if (Field.isBitField()) { + uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset); + unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits; + unsigned Width = Field.getBitWidthValue(C); + PrintBitFieldOffset(OS, FieldOffset, Begin, Width, IndentLevel); + } else { + PrintOffset(OS, FieldOffset, IndentLevel); + } OS << Field.getType().getAsString() << ' ' << Field << '\n'; } - if (!IncludeVirtualBases) - return; - // Dump virtual bases. - const ASTRecordLayout::VBaseOffsetsMapTy &vtordisps = - Layout.getVBaseOffsetsMap(); - for (const CXXBaseSpecifier &Base : RD->vbases()) { - assert(Base.isVirtual() && "Found non-virtual class!"); - const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl(); + if (CXXRD && IncludeVirtualBases) { + const ASTRecordLayout::VBaseOffsetsMapTy &VtorDisps = + Layout.getVBaseOffsetsMap(); - CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase); + for (const CXXBaseSpecifier &Base : CXXRD->vbases()) { + assert(Base.isVirtual() && "Found non-virtual class!"); + const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl(); - if (vtordisps.find(VBase)->second.hasVtorDisp()) { - PrintOffset(OS, VBaseOffset - CharUnits::fromQuantity(4), IndentLevel); - OS << "(vtordisp for vbase " << *VBase << ")\n"; - } + CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase); + + if (VtorDisps.find(VBase)->second.hasVtorDisp()) { + PrintOffset(OS, VBaseOffset - CharUnits::fromQuantity(4), IndentLevel); + OS << "(vtordisp for vbase " << *VBase << ")\n"; + } - DumpCXXRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel, - VBase == PrimaryBase ? - "(primary virtual base)" : "(virtual base)", - /*IncludeVirtualBases=*/false); + DumpRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel, + VBase == Layout.getPrimaryBase() ? + "(primary virtual base)" : "(virtual base)", + /*PrintSizeInfo=*/false, + /*IncludeVirtualBases=*/false); + } } + if (!PrintSizeInfo) return; + PrintIndentNoOffset(OS, IndentLevel - 1); OS << "[sizeof=" << Layout.getSize().getQuantity(); - if (!isMsLayout(RD)) + if (CXXRD && !isMsLayout(C)) OS << ", dsize=" << Layout.getDataSize().getQuantity(); - OS << ", align=" << Layout.getAlignment().getQuantity() << '\n'; + OS << ", align=" << Layout.getAlignment().getQuantity(); - PrintIndentNoOffset(OS, IndentLevel - 1); - OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity(); - OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity() << "]\n"; + if (CXXRD) { + OS << ",\n"; + PrintIndentNoOffset(OS, IndentLevel - 1); + OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity(); + OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity(); + } + OS << "]\n"; } void ASTContext::DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple) const { - const ASTRecordLayout &Info = getASTRecordLayout(RD); + if (!Simple) { + ::DumpRecordLayout(OS, RD, *this, CharUnits(), 0, nullptr, + /*PrintSizeInfo*/true, + /*IncludeVirtualBases=*/true); + return; + } - if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) - if (!Simple) - return DumpCXXRecordLayout(OS, CXXRD, *this, CharUnits(), 0, nullptr, - /*IncludeVirtualBases=*/true); + // The "simple" format is designed to be parsed by the + // layout-override testing code. There shouldn't be any external + // uses of this format --- when LLDB overrides a layout, it sets up + // the data structures directly --- so feel free to adjust this as + // you like as long as you also update the rudimentary parser for it + // in libFrontend. + const ASTRecordLayout &Info = getASTRecordLayout(RD); OS << "Type: " << getTypeDeclType(RD).getAsString() << "\n"; - if (!Simple) { - OS << "Record: "; - RD->dump(); - } OS << "\nLayout: "; OS << "<ASTRecordLayout\n"; OS << " Size:" << toBits(Info.getSize()) << "\n"; - if (!isMsLayout(RD)) + if (!isMsLayout(*this)) OS << " DataSize:" << toBits(Info.getDataSize()) << "\n"; OS << " Alignment:" << toBits(Info.getAlignment()) << "\n"; OS << " FieldOffsets: ["; diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index e6292b4..ca63d84 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" @@ -294,14 +295,15 @@ CompoundStmt::CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts, std::copy(Stmts.begin(), Stmts.end(), Body); } -void CompoundStmt::setStmts(const ASTContext &C, Stmt **Stmts, - unsigned NumStmts) { - if (this->Body) +void CompoundStmt::setStmts(const ASTContext &C, ArrayRef<Stmt *> Stmts) { + if (Body) C.Deallocate(Body); - this->CompoundStmtBits.NumStmts = NumStmts; + CompoundStmtBits.NumStmts = Stmts.size(); + assert(CompoundStmtBits.NumStmts == Stmts.size() && + "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); - Body = new (C) Stmt*[NumStmts]; - memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts); + Body = new (C) Stmt*[Stmts.size()]; + std::copy(Stmts.begin(), Stmts.end(), Body); } const char *LabelStmt::getName() const { @@ -675,12 +677,6 @@ void MSAsmStmt::setInputExpr(unsigned i, Expr *E) { Exprs[i + NumOutputs] = E; } -QualType CXXCatchStmt::getCaughtType() const { - if (ExceptionDecl) - return ExceptionDecl->getType(); - return QualType(); -} - //===----------------------------------------------------------------------===// // Constructors //===----------------------------------------------------------------------===// @@ -724,12 +720,7 @@ MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc, } static StringRef copyIntoContext(const ASTContext &C, StringRef str) { - if (str.empty()) - return StringRef(); - size_t size = str.size(); - char *buffer = new (C) char[size]; - memcpy(buffer, str.data(), size); - return StringRef(buffer, size); + return str.copy(C); } void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr, @@ -740,145 +731,29 @@ void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr, assert(NumAsmToks == asmtoks.size()); assert(NumClobbers == clobbers.size()); - unsigned NumExprs = exprs.size(); - assert(NumExprs == NumOutputs + NumInputs); - assert(NumExprs == constraints.size()); + assert(exprs.size() == NumOutputs + NumInputs); + assert(exprs.size() == constraints.size()); AsmStr = copyIntoContext(C, asmstr); - Exprs = new (C) Stmt*[NumExprs]; - for (unsigned i = 0, e = NumExprs; i != e; ++i) - Exprs[i] = exprs[i]; + Exprs = new (C) Stmt*[exprs.size()]; + std::copy(exprs.begin(), exprs.end(), Exprs); - AsmToks = new (C) Token[NumAsmToks]; - for (unsigned i = 0, e = NumAsmToks; i != e; ++i) - AsmToks[i] = asmtoks[i]; + AsmToks = new (C) Token[asmtoks.size()]; + std::copy(asmtoks.begin(), asmtoks.end(), AsmToks); - Constraints = new (C) StringRef[NumExprs]; - for (unsigned i = 0, e = NumExprs; i != e; ++i) { - Constraints[i] = copyIntoContext(C, constraints[i]); - } + Constraints = new (C) StringRef[exprs.size()]; + std::transform(constraints.begin(), constraints.end(), Constraints, + [&](StringRef Constraint) { + return copyIntoContext(C, Constraint); + }); Clobbers = new (C) StringRef[NumClobbers]; - for (unsigned i = 0, e = NumClobbers; i != e; ++i) { - // FIXME: Avoid the allocation/copy if at all possible. - Clobbers[i] = copyIntoContext(C, clobbers[i]); - } -} - -ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, - Stmt *Body, SourceLocation FCL, - SourceLocation RPL) -: Stmt(ObjCForCollectionStmtClass) { - SubExprs[ELEM] = Elem; - SubExprs[COLLECTION] = Collect; - SubExprs[BODY] = Body; - ForLoc = FCL; - RParenLoc = RPL; -} - -ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, - Stmt **CatchStmts, unsigned NumCatchStmts, - Stmt *atFinallyStmt) - : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc), - NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != nullptr) { - Stmt **Stmts = getStmts(); - Stmts[0] = atTryStmt; - for (unsigned I = 0; I != NumCatchStmts; ++I) - Stmts[I + 1] = CatchStmts[I]; - - if (HasFinally) - Stmts[NumCatchStmts + 1] = atFinallyStmt; -} - -ObjCAtTryStmt *ObjCAtTryStmt::Create(const ASTContext &Context, - SourceLocation atTryLoc, - Stmt *atTryStmt, - Stmt **CatchStmts, - unsigned NumCatchStmts, - Stmt *atFinallyStmt) { - unsigned Size = sizeof(ObjCAtTryStmt) + - (1 + NumCatchStmts + (atFinallyStmt != nullptr)) * sizeof(Stmt *); - void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); - return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts, - atFinallyStmt); -} - -ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(const ASTContext &Context, - unsigned NumCatchStmts, - bool HasFinally) { - unsigned Size = sizeof(ObjCAtTryStmt) + - (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *); - void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); - return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally); -} - -SourceLocation ObjCAtTryStmt::getLocEnd() const { - if (HasFinally) - return getFinallyStmt()->getLocEnd(); - if (NumCatchStmts) - return getCatchStmt(NumCatchStmts - 1)->getLocEnd(); - return getTryBody()->getLocEnd(); -} - -CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc, - Stmt *tryBlock, ArrayRef<Stmt*> handlers) { - std::size_t Size = sizeof(CXXTryStmt); - Size += ((handlers.size() + 1) * sizeof(Stmt)); - - void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); - return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers); -} - -CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty, - unsigned numHandlers) { - std::size_t Size = sizeof(CXXTryStmt); - Size += ((numHandlers + 1) * sizeof(Stmt)); - - void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); - return new (Mem) CXXTryStmt(Empty, numHandlers); -} - -CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, - ArrayRef<Stmt*> handlers) - : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(handlers.size()) { - Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); - Stmts[0] = tryBlock; - std::copy(handlers.begin(), handlers.end(), Stmts + 1); -} - -CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt, - Expr *Cond, Expr *Inc, DeclStmt *LoopVar, - Stmt *Body, SourceLocation FL, - SourceLocation CL, SourceLocation RPL) - : Stmt(CXXForRangeStmtClass), ForLoc(FL), ColonLoc(CL), RParenLoc(RPL) { - SubExprs[RANGE] = Range; - SubExprs[BEGINEND] = BeginEndStmt; - SubExprs[COND] = Cond; - SubExprs[INC] = Inc; - SubExprs[LOOPVAR] = LoopVar; - SubExprs[BODY] = Body; -} - -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"); - return RangeDecl->getInit(); -} - -const Expr *CXXForRangeStmt::getRangeInit() const { - return const_cast<CXXForRangeStmt*>(this)->getRangeInit(); -} - -VarDecl *CXXForRangeStmt::getLoopVariable() { - Decl *LV = cast<DeclStmt>(getLoopVarStmt())->getSingleDecl(); - assert(LV && "No loop variable in CXXForRangeStmt"); - return cast<VarDecl>(LV); -} - -const VarDecl *CXXForRangeStmt::getLoopVariable() const { - return const_cast<CXXForRangeStmt*>(this)->getLoopVariable(); + // FIXME: Avoid the allocation/copy if at all possible. + std::transform(clobbers.begin(), clobbers.end(), Clobbers, + [&](StringRef Clobber) { + return copyIntoContext(C, Clobber); + }); } IfStmt::IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, @@ -1070,6 +945,44 @@ SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc, return new(C)SEHFinallyStmt(Loc,Block); } +CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind, + VarDecl *Var) + : VarAndKind(Var, Kind), Loc(Loc) { + switch (Kind) { + case VCK_This: + assert(!Var && "'this' capture cannot have a variable!"); + break; + case VCK_ByRef: + assert(Var && "capturing by reference must have a variable!"); + break; + case VCK_ByCopy: + assert(Var && "capturing by copy must have a variable!"); + assert( + (Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && + Var->getType() + ->castAs<ReferenceType>() + ->getPointeeType() + ->isScalarType())) && + "captures by copy are expected to have a scalar type!"); + break; + case VCK_VLAType: + assert(!Var && + "Variable-length array type capture cannot have a variable!"); + break; + } +} + +CapturedStmt::VariableCaptureKind +CapturedStmt::Capture::getCaptureKind() const { + return VarAndKind.getInt(); +} + +VarDecl *CapturedStmt::Capture::getCapturedVar() const { + assert((capturesVariable() || capturesVariableByCopy()) && + "No variable available for 'this' or VAT capture"); + return VarAndKind.getPointer(); +} + CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const { unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); @@ -1158,6 +1071,29 @@ Stmt::child_range CapturedStmt::children() { return child_range(getStoredStmts(), getStoredStmts() + NumCaptures); } +CapturedDecl *CapturedStmt::getCapturedDecl() { + return CapDeclAndKind.getPointer(); +} +const CapturedDecl *CapturedStmt::getCapturedDecl() const { + return CapDeclAndKind.getPointer(); +} + +/// \brief Set the outlined function declaration. +void CapturedStmt::setCapturedDecl(CapturedDecl *D) { + assert(D && "null CapturedDecl"); + CapDeclAndKind.setPointer(D); +} + +/// \brief Retrieve the captured region kind. +CapturedRegionKind CapturedStmt::getCapturedRegionKind() const { + return CapDeclAndKind.getInt(); +} + +/// \brief Set the captured region kind. +void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) { + CapDeclAndKind.setInt(Kind); +} + bool CapturedStmt::capturesVariable(const VarDecl *Var) const { for (const auto &I : captures()) { if (!I.capturesVariable()) @@ -1172,1095 +1108,3 @@ bool CapturedStmt::capturesVariable(const VarDecl *Var) const { return false; } - -StmtRange OMPClause::children() { - switch(getClauseKind()) { - default : break; -#define OPENMP_CLAUSE(Name, Class) \ - case OMPC_ ## Name : return static_cast<Class *>(this)->children(); -#include "clang/Basic/OpenMPKinds.def" - } - llvm_unreachable("unknown OMPClause"); -} - -void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) { - assert(VL.size() == varlist_size() && - "Number of private copies is not the same as the preallocated buffer"); - std::copy(VL.begin(), VL.end(), varlist_end()); -} - -OMPPrivateClause * -OMPPrivateClause::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, - ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL) { - // Allocate space for private variables and initializer expressions. - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause), - llvm::alignOf<Expr *>()) + - 2 * sizeof(Expr *) * VL.size()); - OMPPrivateClause *Clause = - new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); - Clause->setPrivateCopies(PrivateVL); - return Clause; -} - -OMPPrivateClause *OMPPrivateClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause), - llvm::alignOf<Expr *>()) + - 2 * sizeof(Expr *) * N); - return new (Mem) OMPPrivateClause(N); -} - -void OMPFirstprivateClause::setPrivateCopies(ArrayRef<Expr *> VL) { - assert(VL.size() == varlist_size() && - "Number of private copies is not the same as the preallocated buffer"); - std::copy(VL.begin(), VL.end(), varlist_end()); -} - -void OMPFirstprivateClause::setInits(ArrayRef<Expr *> VL) { - assert(VL.size() == varlist_size() && - "Number of inits is not the same as the preallocated buffer"); - std::copy(VL.begin(), VL.end(), getPrivateCopies().end()); -} - -OMPFirstprivateClause * -OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, - ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL, - ArrayRef<Expr *> InitVL) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFirstprivateClause), - llvm::alignOf<Expr *>()) + - 3 * sizeof(Expr *) * VL.size()); - OMPFirstprivateClause *Clause = - new (Mem) OMPFirstprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); - Clause->setPrivateCopies(PrivateVL); - Clause->setInits(InitVL); - return Clause; -} - -OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFirstprivateClause), - llvm::alignOf<Expr *>()) + - 3 * sizeof(Expr *) * N); - return new (Mem) OMPFirstprivateClause(N); -} - -void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) { - assert(PrivateCopies.size() == varlist_size() && - "Number of private copies is not the same as the preallocated buffer"); - std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end()); -} - -void OMPLastprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { - assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " - "not the same as the " - "preallocated buffer"); - std::copy(SrcExprs.begin(), SrcExprs.end(), getPrivateCopies().end()); -} - -void OMPLastprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { - assert(DstExprs.size() == varlist_size() && "Number of destination " - "expressions is not the same as " - "the preallocated buffer"); - std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); -} - -void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { - assert(AssignmentOps.size() == varlist_size() && - "Number of assignment expressions is not the same as the preallocated " - "buffer"); - std::copy(AssignmentOps.begin(), AssignmentOps.end(), - getDestinationExprs().end()); -} - -OMPLastprivateClause *OMPLastprivateClause::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, - ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause), - llvm::alignOf<Expr *>()) + - 5 * sizeof(Expr *) * VL.size()); - OMPLastprivateClause *Clause = - new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); - Clause->setSourceExprs(SrcExprs); - Clause->setDestinationExprs(DstExprs); - Clause->setAssignmentOps(AssignmentOps); - return Clause; -} - -OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause), - llvm::alignOf<Expr *>()) + - 5 * 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(llvm::RoundUpToAlignment(sizeof(OMPSharedClause), - llvm::alignOf<Expr *>()) + - sizeof(Expr *) * VL.size()); - OMPSharedClause *Clause = new (Mem) OMPSharedClause(StartLoc, LParenLoc, - EndLoc, VL.size()); - Clause->setVarRefs(VL); - return Clause; -} - -OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPSharedClause), - llvm::alignOf<Expr *>()) + - sizeof(Expr *) * N); - return new (Mem) OMPSharedClause(N); -} - -void OMPLinearClause::setInits(ArrayRef<Expr *> IL) { - assert(IL.size() == varlist_size() && - "Number of inits is not the same as the preallocated buffer"); - std::copy(IL.begin(), IL.end(), varlist_end()); -} - -void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) { - assert(UL.size() == varlist_size() && - "Number of updates is not the same as the preallocated buffer"); - std::copy(UL.begin(), UL.end(), getInits().end()); -} - -void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) { - assert(FL.size() == varlist_size() && - "Number of final updates is not the same as the preallocated buffer"); - std::copy(FL.begin(), FL.end(), getUpdates().end()); -} - -OMPLinearClause * -OMPLinearClause::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation ColonLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, - ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep) { - // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions - // (Step and CalcStep). - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause), - llvm::alignOf<Expr *>()) + - (4 * VL.size() + 2) * sizeof(Expr *)); - OMPLinearClause *Clause = new (Mem) - OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); - Clause->setInits(IL); - // Fill update and final expressions with zeroes, they are provided later, - // after the directive construction. - std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(), - nullptr); - std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(), - nullptr); - Clause->setStep(Step); - Clause->setCalcStep(CalcStep); - return Clause; -} - -OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C, - unsigned NumVars) { - // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions - // (Step and CalcStep). - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause), - llvm::alignOf<Expr *>()) + - (4 * NumVars + 2) * sizeof(Expr *)); - 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); -} - -void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { - assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " - "not the same as the " - "preallocated buffer"); - std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end()); -} - -void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { - assert(DstExprs.size() == varlist_size() && "Number of destination " - "expressions is not the same as " - "the preallocated buffer"); - std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); -} - -void OMPCopyinClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { - assert(AssignmentOps.size() == varlist_size() && - "Number of assignment expressions is not the same as the preallocated " - "buffer"); - std::copy(AssignmentOps.begin(), AssignmentOps.end(), - getDestinationExprs().end()); -} - -OMPCopyinClause *OMPCopyinClause::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, - ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause), - llvm::alignOf<Expr *>()) + - 4 * sizeof(Expr *) * VL.size()); - OMPCopyinClause *Clause = new (Mem) OMPCopyinClause(StartLoc, LParenLoc, - EndLoc, VL.size()); - Clause->setVarRefs(VL); - Clause->setSourceExprs(SrcExprs); - Clause->setDestinationExprs(DstExprs); - Clause->setAssignmentOps(AssignmentOps); - return Clause; -} - -OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause), - llvm::alignOf<Expr *>()) + - 4 * sizeof(Expr *) * N); - return new (Mem) OMPCopyinClause(N); -} - -void OMPCopyprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { - assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " - "not the same as the " - "preallocated buffer"); - std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end()); -} - -void OMPCopyprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { - assert(DstExprs.size() == varlist_size() && "Number of destination " - "expressions is not the same as " - "the preallocated buffer"); - std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); -} - -void OMPCopyprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { - assert(AssignmentOps.size() == varlist_size() && - "Number of assignment expressions is not the same as the preallocated " - "buffer"); - std::copy(AssignmentOps.begin(), AssignmentOps.end(), - getDestinationExprs().end()); -} - -OMPCopyprivateClause *OMPCopyprivateClause::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, - ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause), - llvm::alignOf<Expr *>()) + - 4 * sizeof(Expr *) * VL.size()); - OMPCopyprivateClause *Clause = - new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); - Clause->setSourceExprs(SrcExprs); - Clause->setDestinationExprs(DstExprs); - Clause->setAssignmentOps(AssignmentOps); - return Clause; -} - -OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause), - llvm::alignOf<Expr *>()) + - 4 * sizeof(Expr *) * N); - return new (Mem) OMPCopyprivateClause(N); -} - -void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) { - assert(Clauses.size() == getNumClauses() && - "Number of clauses is not the same as the preallocated buffer"); - std::copy(Clauses.begin(), Clauses.end(), getClauses().begin()); -} - -void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) { - assert(A.size() == getCollapsedNumber() && - "Number of loop counters is not the same as the collapsed number"); - std::copy(A.begin(), A.end(), getCounters().begin()); -} - -void OMPLoopDirective::setInits(ArrayRef<Expr *> A) { - assert(A.size() == getCollapsedNumber() && - "Number of counter inits is not the same as the collapsed number"); - std::copy(A.begin(), A.end(), getInits().begin()); -} - -void OMPLoopDirective::setUpdates(ArrayRef<Expr *> A) { - assert(A.size() == getCollapsedNumber() && - "Number of counter updates is not the same as the collapsed number"); - std::copy(A.begin(), A.end(), getUpdates().begin()); -} - -void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) { - assert(A.size() == getCollapsedNumber() && - "Number of counter finals is not the same as the collapsed number"); - std::copy(A.begin(), A.end(), getFinals().begin()); -} - -void OMPReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) { - assert( - LHSExprs.size() == varlist_size() && - "Number of LHS expressions is not the same as the preallocated buffer"); - std::copy(LHSExprs.begin(), LHSExprs.end(), varlist_end()); -} - -void OMPReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) { - assert( - RHSExprs.size() == varlist_size() && - "Number of RHS expressions is not the same as the preallocated buffer"); - std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end()); -} - -void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) { - assert(ReductionOps.size() == varlist_size() && "Number of reduction " - "expressions is not the same " - "as the preallocated buffer"); - std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end()); -} - -OMPReductionClause *OMPReductionClause::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL, - NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, - ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs, - ArrayRef<Expr *> ReductionOps) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause), - llvm::alignOf<Expr *>()) + - 4 * sizeof(Expr *) * VL.size()); - OMPReductionClause *Clause = new (Mem) OMPReductionClause( - StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo); - Clause->setVarRefs(VL); - Clause->setLHSExprs(LHSExprs); - Clause->setRHSExprs(RHSExprs); - Clause->setReductionOps(ReductionOps); - return Clause; -} - -OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C, - unsigned N) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause), - llvm::alignOf<Expr *>()) + - 4 * 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); -} - -OMPDependClause * -OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, - OpenMPDependClauseKind DepKind, SourceLocation DepLoc, - SourceLocation ColonLoc, ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPDependClause), - llvm::alignOf<Expr *>()) + - sizeof(Expr *) * VL.size()); - OMPDependClause *Clause = - new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); - Clause->setDependencyKind(DepKind); - Clause->setDependencyLoc(DepLoc); - Clause->setColonLoc(ColonLoc); - return Clause; -} - -OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) { - void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPDependClause), - llvm::alignOf<Expr *>()) + - sizeof(Expr *) * N); - return new (Mem) OMPDependClause(N); -} - -const OMPClause * -OMPExecutableDirective::getSingleClause(OpenMPClauseKind K) const { - auto &&I = getClausesOfKind(K); - - if (I) { - auto *Clause = *I; - assert(!++I && "There are at least 2 clauses of the specified kind"); - return Clause; - } - return nullptr; -} - -OMPParallelDirective *OMPParallelDirective::Create( - const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt) { - 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); - Dir->setAssociatedStmt(AssociatedStmt); - return Dir; -} - -OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C, - 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, - const HelperExprs &Exprs) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + - sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd)); - OMPSimdDirective *Dir = new (Mem) - OMPSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); - Dir->setClauses(Clauses); - Dir->setAssociatedStmt(AssociatedStmt); - Dir->setIterationVariable(Exprs.IterationVarRef); - Dir->setLastIteration(Exprs.LastIteration); - Dir->setCalcLastIteration(Exprs.CalcLastIteration); - Dir->setPreCond(Exprs.PreCond); - Dir->setCond(Exprs.Cond); - Dir->setInit(Exprs.Init); - Dir->setInc(Exprs.Inc); - Dir->setCounters(Exprs.Counters); - Dir->setInits(Exprs.Inits); - Dir->setUpdates(Exprs.Updates); - Dir->setFinals(Exprs.Finals); - 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 *) * numLoopChildren(CollapsedNum, OMPD_simd)); - return new (Mem) OMPSimdDirective(CollapsedNum, NumClauses); -} - -OMPForDirective * -OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, unsigned CollapsedNum, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, - const HelperExprs &Exprs) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + - sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); - OMPForDirective *Dir = - new (Mem) OMPForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); - Dir->setClauses(Clauses); - Dir->setAssociatedStmt(AssociatedStmt); - Dir->setIterationVariable(Exprs.IterationVarRef); - Dir->setLastIteration(Exprs.LastIteration); - Dir->setCalcLastIteration(Exprs.CalcLastIteration); - Dir->setPreCond(Exprs.PreCond); - Dir->setCond(Exprs.Cond); - Dir->setInit(Exprs.Init); - Dir->setInc(Exprs.Inc); - Dir->setIsLastIterVariable(Exprs.IL); - Dir->setLowerBoundVariable(Exprs.LB); - Dir->setUpperBoundVariable(Exprs.UB); - Dir->setStrideVariable(Exprs.ST); - Dir->setEnsureUpperBound(Exprs.EUB); - Dir->setNextLowerBound(Exprs.NLB); - Dir->setNextUpperBound(Exprs.NUB); - Dir->setCounters(Exprs.Counters); - Dir->setInits(Exprs.Inits); - Dir->setUpdates(Exprs.Updates); - Dir->setFinals(Exprs.Finals); - 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 *) * numLoopChildren(CollapsedNum, OMPD_for)); - return new (Mem) OMPForDirective(CollapsedNum, NumClauses); -} - -OMPForSimdDirective * -OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, unsigned CollapsedNum, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, - const HelperExprs &Exprs) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + - sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); - OMPForSimdDirective *Dir = new (Mem) - OMPForSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); - Dir->setClauses(Clauses); - Dir->setAssociatedStmt(AssociatedStmt); - Dir->setIterationVariable(Exprs.IterationVarRef); - Dir->setLastIteration(Exprs.LastIteration); - Dir->setCalcLastIteration(Exprs.CalcLastIteration); - Dir->setPreCond(Exprs.PreCond); - Dir->setCond(Exprs.Cond); - Dir->setInit(Exprs.Init); - Dir->setInc(Exprs.Inc); - Dir->setIsLastIterVariable(Exprs.IL); - Dir->setLowerBoundVariable(Exprs.LB); - Dir->setUpperBoundVariable(Exprs.UB); - Dir->setStrideVariable(Exprs.ST); - Dir->setEnsureUpperBound(Exprs.EUB); - Dir->setNextLowerBound(Exprs.NLB); - Dir->setNextUpperBound(Exprs.NUB); - Dir->setCounters(Exprs.Counters); - Dir->setInits(Exprs.Inits); - Dir->setUpdates(Exprs.Updates); - Dir->setFinals(Exprs.Finals); - return Dir; -} - -OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C, - unsigned NumClauses, - unsigned CollapsedNum, - EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * NumClauses + - sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); - return new (Mem) OMPForSimdDirective(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(OMPSectionDirective), - 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, - const HelperExprs &Exprs) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + - sizeof(Stmt *) * - numLoopChildren(CollapsedNum, OMPD_parallel_for)); - OMPParallelForDirective *Dir = new (Mem) - OMPParallelForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); - Dir->setClauses(Clauses); - Dir->setAssociatedStmt(AssociatedStmt); - Dir->setIterationVariable(Exprs.IterationVarRef); - Dir->setLastIteration(Exprs.LastIteration); - Dir->setCalcLastIteration(Exprs.CalcLastIteration); - Dir->setPreCond(Exprs.PreCond); - Dir->setCond(Exprs.Cond); - Dir->setInit(Exprs.Init); - Dir->setInc(Exprs.Inc); - Dir->setIsLastIterVariable(Exprs.IL); - Dir->setLowerBoundVariable(Exprs.LB); - Dir->setUpperBoundVariable(Exprs.UB); - Dir->setStrideVariable(Exprs.ST); - Dir->setEnsureUpperBound(Exprs.EUB); - Dir->setNextLowerBound(Exprs.NLB); - Dir->setNextUpperBound(Exprs.NUB); - Dir->setCounters(Exprs.Counters); - Dir->setInits(Exprs.Inits); - Dir->setUpdates(Exprs.Updates); - Dir->setFinals(Exprs.Finals); - 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 *) * - numLoopChildren(CollapsedNum, OMPD_parallel_for)); - return new (Mem) OMPParallelForDirective(CollapsedNum, NumClauses); -} - -OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, - const HelperExprs &Exprs) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = C.Allocate( - Size + sizeof(OMPClause *) * Clauses.size() + - sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); - OMPParallelForSimdDirective *Dir = new (Mem) OMPParallelForSimdDirective( - StartLoc, EndLoc, CollapsedNum, Clauses.size()); - Dir->setClauses(Clauses); - Dir->setAssociatedStmt(AssociatedStmt); - Dir->setIterationVariable(Exprs.IterationVarRef); - Dir->setLastIteration(Exprs.LastIteration); - Dir->setCalcLastIteration(Exprs.CalcLastIteration); - Dir->setPreCond(Exprs.PreCond); - Dir->setCond(Exprs.Cond); - Dir->setInit(Exprs.Init); - Dir->setInc(Exprs.Inc); - Dir->setIsLastIterVariable(Exprs.IL); - Dir->setLowerBoundVariable(Exprs.LB); - Dir->setUpperBoundVariable(Exprs.UB); - Dir->setStrideVariable(Exprs.ST); - Dir->setEnsureUpperBound(Exprs.EUB); - Dir->setNextLowerBound(Exprs.NLB); - Dir->setNextUpperBound(Exprs.NUB); - Dir->setCounters(Exprs.Counters); - Dir->setInits(Exprs.Inits); - Dir->setUpdates(Exprs.Updates); - Dir->setFinals(Exprs.Finals); - return Dir; -} - -OMPParallelForSimdDirective * -OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, - unsigned NumClauses, - unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = C.Allocate( - Size + sizeof(OMPClause *) * NumClauses + - sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); - return new (Mem) OMPParallelForSimdDirective(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(OMPTaskwaitDirective)); - return new (Mem) OMPTaskwaitDirective(); -} - -OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - Stmt *AssociatedStmt) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective), - llvm::alignOf<Stmt *>()); - void *Mem = C.Allocate(Size + sizeof(Stmt *)); - OMPTaskgroupDirective *Dir = - new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc); - Dir->setAssociatedStmt(AssociatedStmt); - return Dir; -} - -OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, - EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective), - llvm::alignOf<Stmt *>()); - void *Mem = C.Allocate(Size + sizeof(Stmt *)); - return new (Mem) OMPTaskgroupDirective(); -} - -OMPCancellationPointDirective *OMPCancellationPointDirective::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - OpenMPDirectiveKind CancelRegion) { - unsigned Size = llvm::RoundUpToAlignment( - sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>()); - void *Mem = C.Allocate(Size); - OMPCancellationPointDirective *Dir = - new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc); - Dir->setCancelRegion(CancelRegion); - return Dir; -} - -OMPCancellationPointDirective * -OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment( - sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>()); - void *Mem = C.Allocate(Size); - return new (Mem) OMPCancellationPointDirective(); -} - -OMPCancelDirective * -OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, - OpenMPDirectiveKind CancelRegion) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective), - llvm::alignOf<Stmt *>()); - void *Mem = C.Allocate(Size); - OMPCancelDirective *Dir = new (Mem) OMPCancelDirective(StartLoc, EndLoc); - Dir->setCancelRegion(CancelRegion); - return Dir; -} - -OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C, - EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective), - llvm::alignOf<Stmt *>()); - void *Mem = C.Allocate(Size); - return new (Mem) OMPCancelDirective(); -} - -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); -} - -OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - Stmt *AssociatedStmt) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective), - llvm::alignOf<Stmt *>()); - void *Mem = C.Allocate(Size + sizeof(Stmt *)); - OMPOrderedDirective *Dir = new (Mem) OMPOrderedDirective(StartLoc, EndLoc); - Dir->setAssociatedStmt(AssociatedStmt); - return Dir; -} - -OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, - EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective), - llvm::alignOf<Stmt *>()); - void *Mem = C.Allocate(Size + sizeof(Stmt *)); - return new (Mem) OMPOrderedDirective(); -} - -OMPAtomicDirective *OMPAtomicDirective::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, - Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + - 5 * sizeof(Stmt *)); - OMPAtomicDirective *Dir = - new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size()); - Dir->setClauses(Clauses); - Dir->setAssociatedStmt(AssociatedStmt); - Dir->setX(X); - Dir->setV(V); - Dir->setExpr(E); - Dir->setUpdateExpr(UE); - Dir->IsXLHSInRHSPart = IsXLHSInRHSPart; - Dir->IsPostfixUpdate = IsPostfixUpdate; - return Dir; -} - -OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, - unsigned NumClauses, - EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *)); - return new (Mem) OMPAtomicDirective(NumClauses); -} - -OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); - OMPTargetDirective *Dir = - new (Mem) OMPTargetDirective(StartLoc, EndLoc, Clauses.size()); - Dir->setClauses(Clauses); - Dir->setAssociatedStmt(AssociatedStmt); - return Dir; -} - -OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C, - unsigned NumClauses, - EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); - return new (Mem) OMPTargetDirective(NumClauses); -} - -OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); - OMPTeamsDirective *Dir = - new (Mem) OMPTeamsDirective(StartLoc, EndLoc, Clauses.size()); - Dir->setClauses(Clauses); - Dir->setAssociatedStmt(AssociatedStmt); - return Dir; -} - -OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C, - unsigned NumClauses, - EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective), - llvm::alignOf<OMPClause *>()); - void *Mem = - C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); - return new (Mem) OMPTeamsDirective(NumClauses); -} - diff --git a/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp b/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp new file mode 100644 index 0000000..e39a01d --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp @@ -0,0 +1,86 @@ +//===--- StmtCXX.cpp - Classes for representing C++ statements ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the subclesses of Stmt class declared in StmtCXX.h +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/StmtCXX.h" + +#include "clang/AST/ASTContext.h" + +using namespace clang; + +QualType CXXCatchStmt::getCaughtType() const { + if (ExceptionDecl) + return ExceptionDecl->getType(); + return QualType(); +} + +CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc, + Stmt *tryBlock, ArrayRef<Stmt *> handlers) { + std::size_t Size = sizeof(CXXTryStmt); + Size += ((handlers.size() + 1) * sizeof(Stmt *)); + + void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); + return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers); +} + +CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty, + unsigned numHandlers) { + std::size_t Size = sizeof(CXXTryStmt); + Size += ((numHandlers + 1) * sizeof(Stmt *)); + + void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); + return new (Mem) CXXTryStmt(Empty, numHandlers); +} + +CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, + ArrayRef<Stmt *> handlers) + : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(handlers.size()) { + Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); + Stmts[0] = tryBlock; + std::copy(handlers.begin(), handlers.end(), Stmts + 1); +} + +CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt, + Expr *Cond, Expr *Inc, DeclStmt *LoopVar, + Stmt *Body, SourceLocation FL, + SourceLocation CAL, SourceLocation CL, + SourceLocation RPL) + : Stmt(CXXForRangeStmtClass), ForLoc(FL), CoawaitLoc(CAL), ColonLoc(CL), + RParenLoc(RPL) { + SubExprs[RANGE] = Range; + SubExprs[BEGINEND] = BeginEndStmt; + SubExprs[COND] = Cond; + SubExprs[INC] = Inc; + SubExprs[LOOPVAR] = LoopVar; + SubExprs[BODY] = Body; +} + +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"); + return RangeDecl->getInit(); +} + +const Expr *CXXForRangeStmt::getRangeInit() const { + return const_cast<CXXForRangeStmt *>(this)->getRangeInit(); +} + +VarDecl *CXXForRangeStmt::getLoopVariable() { + Decl *LV = cast<DeclStmt>(getLoopVarStmt())->getSingleDecl(); + assert(LV && "No loop variable in CXXForRangeStmt"); + return cast<VarDecl>(LV); +} + +const VarDecl *CXXForRangeStmt::getLoopVariable() const { + return const_cast<CXXForRangeStmt *>(this)->getLoopVariable(); +} diff --git a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp index 732756f..861d090 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp @@ -42,7 +42,7 @@ void StmtIteratorBase::NextVA() { if (inDeclGroup()) { if (VarDecl* VD = dyn_cast<VarDecl>(*DGI)) - if (VD->Init) + if (VD->hasInit()) return; NextDecl(); diff --git a/contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp b/contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp new file mode 100644 index 0000000..a77550c --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp @@ -0,0 +1,73 @@ +//===--- StmtObjC.cpp - Classes for representing ObjC statements ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the subclesses of Stmt class declared in StmtObjC.h +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/StmtObjC.h" + +#include "clang/AST/Expr.h" +#include "clang/AST/ASTContext.h" + +using namespace clang; + +ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, + Stmt *Body, SourceLocation FCL, + SourceLocation RPL) + : Stmt(ObjCForCollectionStmtClass) { + SubExprs[ELEM] = Elem; + SubExprs[COLLECTION] = Collect; + SubExprs[BODY] = Body; + ForLoc = FCL; + RParenLoc = RPL; +} + +ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, + Stmt **CatchStmts, unsigned NumCatchStmts, + Stmt *atFinallyStmt) + : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc), + NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != nullptr) { + Stmt **Stmts = getStmts(); + Stmts[0] = atTryStmt; + for (unsigned I = 0; I != NumCatchStmts; ++I) + Stmts[I + 1] = CatchStmts[I]; + + if (HasFinally) + Stmts[NumCatchStmts + 1] = atFinallyStmt; +} + +ObjCAtTryStmt *ObjCAtTryStmt::Create(const ASTContext &Context, + SourceLocation atTryLoc, Stmt *atTryStmt, + Stmt **CatchStmts, unsigned NumCatchStmts, + Stmt *atFinallyStmt) { + unsigned Size = + sizeof(ObjCAtTryStmt) + + (1 + NumCatchStmts + (atFinallyStmt != nullptr)) * sizeof(Stmt *); + void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); + return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts, + atFinallyStmt); +} + +ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(const ASTContext &Context, + unsigned NumCatchStmts, + bool HasFinally) { + unsigned Size = + sizeof(ObjCAtTryStmt) + (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *); + void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); + return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally); +} + +SourceLocation ObjCAtTryStmt::getLocEnd() const { + if (HasFinally) + return getFinallyStmt()->getLocEnd(); + if (NumCatchStmts) + return getCatchStmt(NumCatchStmts - 1)->getLocEnd(); + return getTryBody()->getLocEnd(); +} diff --git a/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp new file mode 100644 index 0000000..7f923d8 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp @@ -0,0 +1,884 @@ +//===--- StmtOpenMP.cpp - Classes for OpenMP directives -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the subclesses of Stmt class declared in StmtOpenMP.h +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/StmtOpenMP.h" + +#include "clang/AST/ASTContext.h" + +using namespace clang; + +void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) { + assert(Clauses.size() == getNumClauses() && + "Number of clauses is not the same as the preallocated buffer"); + std::copy(Clauses.begin(), Clauses.end(), getClauses().begin()); +} + +void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) { + assert(A.size() == getCollapsedNumber() && + "Number of loop counters is not the same as the collapsed number"); + std::copy(A.begin(), A.end(), getCounters().begin()); +} + +void OMPLoopDirective::setPrivateCounters(ArrayRef<Expr *> A) { + assert(A.size() == getCollapsedNumber() && "Number of loop private counters " + "is not the same as the collapsed " + "number"); + std::copy(A.begin(), A.end(), getPrivateCounters().begin()); +} + +void OMPLoopDirective::setInits(ArrayRef<Expr *> A) { + assert(A.size() == getCollapsedNumber() && + "Number of counter inits is not the same as the collapsed number"); + std::copy(A.begin(), A.end(), getInits().begin()); +} + +void OMPLoopDirective::setUpdates(ArrayRef<Expr *> A) { + assert(A.size() == getCollapsedNumber() && + "Number of counter updates is not the same as the collapsed number"); + std::copy(A.begin(), A.end(), getUpdates().begin()); +} + +void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) { + assert(A.size() == getCollapsedNumber() && + "Number of counter finals is not the same as the collapsed number"); + std::copy(A.begin(), A.end(), getFinals().begin()); +} + +OMPParallelDirective *OMPParallelDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { + 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); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setHasCancel(HasCancel); + return Dir; +} + +OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C, + 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, + const HelperExprs &Exprs) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd)); + OMPSimdDirective *Dir = new (Mem) + OMPSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + 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 *) * numLoopChildren(CollapsedNum, OMPD_simd)); + return new (Mem) OMPSimdDirective(CollapsedNum, NumClauses); +} + +OMPForDirective * +OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs, bool HasCancel) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); + OMPForDirective *Dir = + new (Mem) OMPForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setHasCancel(HasCancel); + 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 *) * numLoopChildren(CollapsedNum, OMPD_for)); + return new (Mem) OMPForDirective(CollapsedNum, NumClauses); +} + +OMPForSimdDirective * +OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); + OMPForSimdDirective *Dir = new (Mem) + OMPForSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + return Dir; +} + +OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); + return new (Mem) OMPForSimdDirective(CollapsedNum, NumClauses); +} + +OMPSectionsDirective *OMPSectionsDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { + 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); + Dir->setHasCancel(HasCancel); + 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, + bool HasCancel) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setHasCancel(HasCancel); + 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, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPCriticalDirective *Dir = + new (Mem) OMPCriticalDirective(Name, StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPCriticalDirective(NumClauses); +} + +OMPParallelForDirective *OMPParallelForDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs, bool HasCancel) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_parallel_for)); + OMPParallelForDirective *Dir = new (Mem) + OMPParallelForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setHasCancel(HasCancel); + 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 *) * + numLoopChildren(CollapsedNum, OMPD_parallel_for)); + return new (Mem) OMPParallelForDirective(CollapsedNum, NumClauses); +} + +OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); + OMPParallelForSimdDirective *Dir = new (Mem) OMPParallelForSimdDirective( + StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + return Dir; +} + +OMPParallelForSimdDirective * +OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); + return new (Mem) OMPParallelForSimdDirective(CollapsedNum, NumClauses); +} + +OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) { + 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); + Dir->setHasCancel(HasCancel); + 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, bool HasCancel) { + 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); + Dir->setHasCancel(HasCancel); + 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(OMPTaskwaitDirective)); + return new (Mem) OMPTaskwaitDirective(); +} + +OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + OMPTaskgroupDirective *Dir = + new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + return new (Mem) OMPTaskgroupDirective(); +} + +OMPCancellationPointDirective *OMPCancellationPointDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + OpenMPDirectiveKind CancelRegion) { + unsigned Size = llvm::RoundUpToAlignment( + sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size); + OMPCancellationPointDirective *Dir = + new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc); + Dir->setCancelRegion(CancelRegion); + return Dir; +} + +OMPCancellationPointDirective * +OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment( + sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size); + return new (Mem) OMPCancellationPointDirective(); +} + +OMPCancelDirective * +OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, + OpenMPDirectiveKind CancelRegion) { + unsigned Size = llvm::RoundUpToAlignment( + sizeof(OMPCancelDirective) + sizeof(OMPClause *) * Clauses.size(), + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size); + OMPCancelDirective *Dir = + new (Mem) OMPCancelDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setCancelRegion(CancelRegion); + return Dir; +} + +OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective) + + sizeof(OMPClause *) * NumClauses, + llvm::alignOf<Stmt *>()); + void *Mem = C.Allocate(Size); + return new (Mem) OMPCancelDirective(NumClauses); +} + +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); +} + +OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * Clauses.size()); + OMPOrderedDirective *Dir = + new (Mem) OMPOrderedDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * NumClauses); + return new (Mem) OMPOrderedDirective(NumClauses); +} + +OMPAtomicDirective *OMPAtomicDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, + Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + 5 * sizeof(Stmt *)); + OMPAtomicDirective *Dir = + new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setX(X); + Dir->setV(V); + Dir->setExpr(E); + Dir->setUpdateExpr(UE); + Dir->IsXLHSInRHSPart = IsXLHSInRHSPart; + Dir->IsPostfixUpdate = IsPostfixUpdate; + return Dir; +} + +OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *)); + return new (Mem) OMPAtomicDirective(NumClauses); +} + +OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTargetDirective *Dir = + new (Mem) OMPTargetDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTargetDirective(NumClauses); +} + +OMPTargetDataDirective *OMPTargetDataDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + void *Mem = + C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPTargetDataDirective), + llvm::alignOf<OMPClause *>()) + + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTargetDataDirective *Dir = + new (Mem) OMPTargetDataDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTargetDataDirective *OMPTargetDataDirective::CreateEmpty(const ASTContext &C, + unsigned N, + EmptyShell) { + void *Mem = + C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPTargetDataDirective), + llvm::alignOf<OMPClause *>()) + + sizeof(OMPClause *) * N + sizeof(Stmt *)); + return new (Mem) OMPTargetDataDirective(N); +} + +OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTeamsDirective *Dir = + new (Mem) OMPTeamsDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTeamsDirective(NumClauses); +} + +OMPTaskLoopDirective *OMPTaskLoopDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskLoopDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop)); + OMPTaskLoopDirective *Dir = new (Mem) + OMPTaskLoopDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + return Dir; +} + +OMPTaskLoopDirective *OMPTaskLoopDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskLoopDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop)); + return new (Mem) OMPTaskLoopDirective(CollapsedNum, NumClauses); +} + +OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskLoopSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_taskloop_simd)); + OMPTaskLoopSimdDirective *Dir = new (Mem) + OMPTaskLoopSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + return Dir; +} + +OMPTaskLoopSimdDirective * +OMPTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskLoopSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_taskloop_simd)); + return new (Mem) OMPTaskLoopSimdDirective(CollapsedNum, NumClauses); +} + +OMPDistributeDirective *OMPDistributeDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPDistributeDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_distribute)); + OMPDistributeDirective *Dir = new (Mem) + OMPDistributeDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + Dir->setIterationVariable(Exprs.IterationVarRef); + Dir->setLastIteration(Exprs.LastIteration); + Dir->setCalcLastIteration(Exprs.CalcLastIteration); + Dir->setPreCond(Exprs.PreCond); + Dir->setCond(Exprs.Cond); + Dir->setInit(Exprs.Init); + Dir->setInc(Exprs.Inc); + Dir->setIsLastIterVariable(Exprs.IL); + Dir->setLowerBoundVariable(Exprs.LB); + Dir->setUpperBoundVariable(Exprs.UB); + Dir->setStrideVariable(Exprs.ST); + Dir->setEnsureUpperBound(Exprs.EUB); + Dir->setNextLowerBound(Exprs.NLB); + Dir->setNextUpperBound(Exprs.NUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + return Dir; +} + +OMPDistributeDirective * +OMPDistributeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPDistributeDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_distribute)); + return new (Mem) OMPDistributeDirective(CollapsedNum, NumClauses); +} diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index 7960077..69f52f5 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -19,6 +19,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/CharInfo.h" @@ -601,6 +602,8 @@ public: void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) { OS << "if("; + if (Node->getNameModifier() != OMPD_unknown) + OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": "; Node->getCondition()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } @@ -623,6 +626,12 @@ void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) { OS << ")"; } +void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) { + OS << "simdlen("; + Node->getSimdlen()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) { OS << "collapse("; Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0); @@ -642,8 +651,18 @@ void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) { } void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) { - OS << "schedule(" - << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind()); + OS << "schedule("; + if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) { + OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, + Node->getFirstScheduleModifier()); + if (Node->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) { + OS << ", "; + OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, + Node->getSecondScheduleModifier()); + } + OS << ": "; + } + OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind()); if (Node->getChunkSize()) { OS << ", "; Node->getChunkSize()->printPretty(OS, nullptr, Policy); @@ -651,8 +670,13 @@ void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) { OS << ")"; } -void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *) { +void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *Node) { OS << "ordered"; + if (auto *Num = Node->getNumForLoops()) { + OS << "("; + Num->printPretty(OS, nullptr, Policy, 0); + OS << ")"; + } } void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) { @@ -663,6 +687,10 @@ void OMPClausePrinter::VisitOMPUntiedClause(OMPUntiedClause *) { OS << "untied"; } +void OMPClausePrinter::VisitOMPNogroupClause(OMPNogroupClause *) { + OS << "nogroup"; +} + void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) { OS << "mergeable"; } @@ -683,6 +711,54 @@ void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) { OS << "seq_cst"; } +void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) { + OS << "threads"; +} + +void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; } + +void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) { + OS << "device("; + Node->getDevice()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) { + OS << "num_teams("; + Node->getNumTeams()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPThreadLimitClause(OMPThreadLimitClause *Node) { + OS << "thread_limit("; + Node->getThreadLimit()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPPriorityClause(OMPPriorityClause *Node) { + OS << "priority("; + Node->getPriority()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPGrainsizeClause(OMPGrainsizeClause *Node) { + OS << "grainsize("; + Node->getGrainsize()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) { + OS << "num_tasks("; + Node->getNumTasks()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) { + OS << "hint("; + Node->getHint()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + template<typename T> void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) { for (typename T::varlist_iterator I = Node->varlist_begin(), @@ -756,7 +832,13 @@ void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) { void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) { if (!Node->varlist_empty()) { OS << "linear"; + if (Node->getModifierLoc().isValid()) { + OS << '(' + << getOpenMPSimpleClauseTypeName(OMPC_linear, Node->getModifier()); + } VisitOMPClauseList(Node, '('); + if (Node->getModifierLoc().isValid()) + OS << ')'; if (Node->getStep() != nullptr) { OS << ": "; Node->getStep()->printPretty(OS, nullptr, Policy, 0); @@ -801,11 +883,28 @@ void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) { } void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) { + OS << "depend("; + OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), + Node->getDependencyKind()); + if (!Node->varlist_empty()) { + OS << " :"; + VisitOMPClauseList(Node, ' '); + } + OS << ")"; +} + +void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) { if (!Node->varlist_empty()) { - OS << "depend("; - OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), - Node->getDependencyKind()) - << " :"; + OS << "map("; + if (Node->getMapType() != OMPC_MAP_unknown) { + if (Node->getMapTypeModifier() != OMPC_MAP_unknown) { + OS << getOpenMPSimpleClauseTypeName(OMPC_map, + Node->getMapTypeModifier()); + OS << ','; + } + OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapType()); + OS << ':'; + } VisitOMPClauseList(Node, ' '); OS << ")"; } @@ -881,6 +980,7 @@ void StmtPrinter::VisitOMPCriticalDirective(OMPCriticalDirective *Node) { Node->getDirectiveName().printName(OS); OS << ")"; } + OS << " "; PrintOMPExecutableDirective(Node); } @@ -932,7 +1032,7 @@ void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) { } void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) { - Indent() << "#pragma omp ordered"; + Indent() << "#pragma omp ordered "; PrintOMPExecutableDirective(Node); } @@ -946,6 +1046,11 @@ void StmtPrinter::VisitOMPTargetDirective(OMPTargetDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTargetDataDirective(OMPTargetDataDirective *Node) { + Indent() << "#pragma omp target data "; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) { Indent() << "#pragma omp teams "; PrintOMPExecutableDirective(Node); @@ -960,9 +1065,26 @@ void StmtPrinter::VisitOMPCancellationPointDirective( void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) { Indent() << "#pragma omp cancel " - << getOpenMPDirectiveName(Node->getCancelRegion()); + << getOpenMPDirectiveName(Node->getCancelRegion()) << " "; PrintOMPExecutableDirective(Node); } + +void StmtPrinter::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *Node) { + Indent() << "#pragma omp taskloop "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTaskLoopSimdDirective( + OMPTaskLoopSimdDirective *Node) { + Indent() << "#pragma omp taskloop simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) { + Indent() << "#pragma omp distribute "; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// @@ -1043,6 +1165,7 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { switch (Node->getKind()) { case CharacterLiteral::Ascii: break; // no prefix. case CharacterLiteral::Wide: OS << 'L'; break; + case CharacterLiteral::UTF8: OS << "u8"; break; case CharacterLiteral::UTF16: OS << 'u'; break; case CharacterLiteral::UTF32: OS << 'U'; break; } @@ -1110,8 +1233,6 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { case BuiltinType::ULong: OS << "UL"; break; case BuiltinType::LongLong: OS << "LL"; break; case BuiltinType::ULongLong: OS << "ULL"; break; - case BuiltinType::Int128: OS << "i128"; break; - case BuiltinType::UInt128: OS << "Ui128"; break; } } @@ -1185,8 +1306,8 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) { OS << ", "; bool PrintedSomething = false; for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) { - OffsetOfExpr::OffsetOfNode ON = Node->getComponent(i); - if (ON.getKind() == OffsetOfExpr::OffsetOfNode::Array) { + OffsetOfNode ON = Node->getComponent(i); + if (ON.getKind() == OffsetOfNode::Array) { // Array node OS << "["; PrintExpr(Node->getIndexExpr(ON.getArrayExprIndex())); @@ -1196,7 +1317,7 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) { } // Skip implicit base indirections. - if (ON.getKind() == OffsetOfExpr::OffsetOfNode::Base) + if (ON.getKind() == OffsetOfNode::Base) continue; // Field or identifier node. @@ -1266,6 +1387,19 @@ void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) { OS << "]"; } +void StmtPrinter::VisitOMPArraySectionExpr(OMPArraySectionExpr *Node) { + PrintExpr(Node->getBase()); + OS << "["; + if (Node->getLowerBound()) + PrintExpr(Node->getLowerBound()); + if (Node->getColonLoc().isValid()) { + OS << ":"; + if (Node->getLength()) + PrintExpr(Node->getLength()); + } + OS << "]"; +} + void StmtPrinter::PrintCallArgs(CallExpr *Call) { for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) { if (isa<CXXDefaultArgExpr>(Call->getArg(i))) { @@ -1667,6 +1801,13 @@ void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) { OS << Node->getPropertyDecl()->getDeclName(); } +void StmtPrinter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *Node) { + PrintExpr(Node->getBase()); + OS << "["; + PrintExpr(Node->getIdx()); + OS << "]"; +} + void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { switch (Node->getLiteralOperatorKind()) { case UserDefinedLiteral::LOK_Raw: @@ -1679,7 +1820,7 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { assert(Args); if (Args->size() != 1) { - OS << "operator \"\" " << Node->getUDSuffix()->getName(); + OS << "operator\"\"" << Node->getUDSuffix()->getName(); TemplateSpecializationType::PrintTemplateArgumentList( OS, Args->data(), Args->size(), Policy); OS << "()"; @@ -1768,7 +1909,7 @@ void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(), ArgEnd = Node->arg_end(); Arg != ArgEnd; ++Arg) { - if (Arg->isDefaultArgument()) + if ((*Arg)->isDefaultArgument()) break; if (Arg != Node->arg_begin()) OS << ", "; @@ -2115,6 +2256,31 @@ void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) { OS << ")"; } +// C++ Coroutines TS + +void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) { + Visit(S->getBody()); +} + +void StmtPrinter::VisitCoreturnStmt(CoreturnStmt *S) { + OS << "co_return"; + if (S->getOperand()) { + OS << " "; + Visit(S->getOperand()); + } + OS << ";"; +} + +void StmtPrinter::VisitCoawaitExpr(CoawaitExpr *S) { + OS << "co_await "; + PrintExpr(S->getOperand()); +} + +void StmtPrinter::VisitCoyieldExpr(CoyieldExpr *S) { + OS << "co_yield "; + PrintExpr(S->getOperand()); +} + // Obj-C void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) { @@ -2129,14 +2295,11 @@ void StmtPrinter::VisitObjCBoxedExpr(ObjCBoxedExpr *E) { void StmtPrinter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) { OS << "@[ "; - StmtRange ch = E->children(); - if (ch.first != ch.second) { - while (1) { - Visit(*ch.first); - ++ch.first; - if (ch.first == ch.second) break; + ObjCArrayLiteral::child_range Ch = E->children(); + for (auto I = Ch.begin(), E = Ch.end(); I != E; ++I) { + if (I != Ch.begin()) OS << ", "; - } + Visit(*I); } OS << " ]"; } diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index da99692..175a43a 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -18,6 +18,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/StmtVisitor.h" #include "llvm/ADT/FoldingSet.h" using namespace clang; @@ -261,6 +262,7 @@ class OMPClauseProfiler : public ConstOMPClauseVisitor<OMPClauseProfiler> { /// \brief Process clauses with list of variables. template <typename T> void VisitOMPClauseList(T *Node); + public: OMPClauseProfiler(StmtProfiler *P) : Profiler(P) { } #define OPENMP_CLAUSE(Name, Class) \ @@ -288,6 +290,11 @@ void OMPClauseProfiler::VisitOMPSafelenClause(const OMPSafelenClause *C) { Profiler->VisitStmt(C->getSafelen()); } +void OMPClauseProfiler::VisitOMPSimdlenClause(const OMPSimdlenClause *C) { + if (C->getSimdlen()) + Profiler->VisitStmt(C->getSimdlen()); +} + void OMPClauseProfiler::VisitOMPCollapseClause(const OMPCollapseClause *C) { if (C->getNumForLoops()) Profiler->VisitStmt(C->getNumForLoops()); @@ -306,7 +313,10 @@ void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) { } } -void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *) {} +void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *C) { + if (auto *Num = C->getNumForLoops()) + Profiler->VisitStmt(Num); +} void OMPClauseProfiler::VisitOMPNowaitClause(const OMPNowaitClause *) {} @@ -324,6 +334,12 @@ void OMPClauseProfiler::VisitOMPCaptureClause(const OMPCaptureClause *) {} void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {} +void OMPClauseProfiler::VisitOMPThreadsClause(const OMPThreadsClause *) {} + +void OMPClauseProfiler::VisitOMPSIMDClause(const OMPSIMDClause *) {} + +void OMPClauseProfiler::VisitOMPNogroupClause(const OMPNogroupClause *) {} + template<typename T> void OMPClauseProfiler::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { @@ -369,6 +385,9 @@ void OMPClauseProfiler::VisitOMPReductionClause( C->getQualifierLoc().getNestedNameSpecifier()); Profiler->VisitName(C->getNameInfo().getName()); VisitOMPClauseList(C); + for (auto *E : C->privates()) { + Profiler->VisitStmt(E); + } for (auto *E : C->lhs_exprs()) { Profiler->VisitStmt(E); } @@ -381,6 +400,9 @@ void OMPClauseProfiler::VisitOMPReductionClause( } void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) { VisitOMPClauseList(C); + for (auto *E : C->privates()) { + Profiler->VisitStmt(E); + } for (auto *E : C->inits()) { Profiler->VisitStmt(E); } @@ -428,6 +450,31 @@ void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) { void OMPClauseProfiler::VisitOMPDependClause(const OMPDependClause *C) { VisitOMPClauseList(C); } +void OMPClauseProfiler::VisitOMPDeviceClause(const OMPDeviceClause *C) { + Profiler->VisitStmt(C->getDevice()); +} +void OMPClauseProfiler::VisitOMPMapClause(const OMPMapClause *C) { + VisitOMPClauseList(C); +} +void OMPClauseProfiler::VisitOMPNumTeamsClause(const OMPNumTeamsClause *C) { + Profiler->VisitStmt(C->getNumTeams()); +} +void OMPClauseProfiler::VisitOMPThreadLimitClause( + const OMPThreadLimitClause *C) { + Profiler->VisitStmt(C->getThreadLimit()); +} +void OMPClauseProfiler::VisitOMPPriorityClause(const OMPPriorityClause *C) { + Profiler->VisitStmt(C->getPriority()); +} +void OMPClauseProfiler::VisitOMPGrainsizeClause(const OMPGrainsizeClause *C) { + Profiler->VisitStmt(C->getGrainsize()); +} +void OMPClauseProfiler::VisitOMPNumTasksClause(const OMPNumTasksClause *C) { + Profiler->VisitStmt(C->getNumTasks()); +} +void OMPClauseProfiler::VisitOMPHintClause(const OMPHintClause *C) { + Profiler->VisitStmt(C->getHint()); +} } void @@ -533,6 +580,10 @@ void StmtProfiler::VisitOMPTargetDirective(const OMPTargetDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPTargetDataDirective(const OMPTargetDataDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitOMPTeamsDirective(const OMPTeamsDirective *S) { VisitOMPExecutableDirective(S); } @@ -546,6 +597,20 @@ void StmtProfiler::VisitOMPCancelDirective(const OMPCancelDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPTaskLoopDirective(const OMPTaskLoopDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTaskLoopSimdDirective( + const OMPTaskLoopSimdDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPDistributeDirective( + const OMPDistributeDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } @@ -610,22 +675,22 @@ void StmtProfiler::VisitOffsetOfExpr(const OffsetOfExpr *S) { VisitType(S->getTypeSourceInfo()->getType()); unsigned n = S->getNumComponents(); for (unsigned i = 0; i < n; ++i) { - const OffsetOfExpr::OffsetOfNode& ON = S->getComponent(i); + const OffsetOfNode &ON = S->getComponent(i); ID.AddInteger(ON.getKind()); switch (ON.getKind()) { - case OffsetOfExpr::OffsetOfNode::Array: + case OffsetOfNode::Array: // Expressions handled below. break; - case OffsetOfExpr::OffsetOfNode::Field: + case OffsetOfNode::Field: VisitDecl(ON.getField()); break; - case OffsetOfExpr::OffsetOfNode::Identifier: + case OffsetOfNode::Identifier: ID.AddPointer(ON.getFieldName()); break; - - case OffsetOfExpr::OffsetOfNode::Base: + + case OffsetOfNode::Base: // These nodes are implicit, and therefore don't need profiling. break; } @@ -646,6 +711,10 @@ void StmtProfiler::VisitArraySubscriptExpr(const ArraySubscriptExpr *S) { VisitExpr(S); } +void StmtProfiler::VisitOMPArraySectionExpr(const OMPArraySectionExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCallExpr(const CallExpr *S) { VisitExpr(S); } @@ -824,6 +893,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, case OO_Arrow: case OO_Call: case OO_Conditional: + case OO_Coawait: case NUM_OVERLOADED_OPERATORS: llvm_unreachable("Invalid operator call kind"); @@ -985,7 +1055,6 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, BinaryOp = BO_Comma; return Stmt::BinaryOperatorClass; - case OO_ArrowStar: BinaryOp = BO_PtrMemI; return Stmt::BinaryOperatorClass; @@ -997,7 +1066,6 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, llvm_unreachable("Invalid overloaded operator expression"); } - void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { if (S->isTypeDependent()) { // Type-dependent operator calls are profiled like their underlying @@ -1092,6 +1160,11 @@ void StmtProfiler::VisitMSPropertyRefExpr(const MSPropertyRefExpr *S) { VisitDecl(S->getPropertyDecl()); } +void StmtProfiler::VisitMSPropertySubscriptExpr( + const MSPropertySubscriptExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) { VisitExpr(S); ID.AddBoolean(S->isImplicit()); @@ -1169,7 +1242,6 @@ void StmtProfiler::VisitCXXDeleteExpr(const CXXDeleteExpr *S) { VisitDecl(S->getOperatorDelete()); } - void StmtProfiler::VisitCXXNewExpr(const CXXNewExpr *S) { VisitExpr(S); VisitType(S->getAllocatedType()); @@ -1203,8 +1275,7 @@ void StmtProfiler::VisitOverloadExpr(const OverloadExpr *S) { VisitName(S->getName()); ID.AddBoolean(S->hasExplicitTemplateArgs()); if (S->hasExplicitTemplateArgs()) - VisitTemplateArguments(S->getExplicitTemplateArgs().getTemplateArgs(), - S->getExplicitTemplateArgs().NumTemplateArgs); + VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); } void @@ -1290,6 +1361,14 @@ void StmtProfiler::VisitPackExpansionExpr(const PackExpansionExpr *S) { void StmtProfiler::VisitSizeOfPackExpr(const SizeOfPackExpr *S) { VisitExpr(S); VisitDecl(S->getPack()); + if (S->isPartiallySubstituted()) { + auto Args = S->getPartialArguments(); + ID.AddInteger(Args.size()); + for (const auto &TA : Args) + VisitTemplateArgument(TA); + } else { + ID.AddInteger(0); + } } void StmtProfiler::VisitSubstNonTypeTemplateParmPackExpr( @@ -1323,6 +1402,22 @@ void StmtProfiler::VisitCXXFoldExpr(const CXXFoldExpr *S) { ID.AddInteger(S->getOperator()); } +void StmtProfiler::VisitCoroutineBodyStmt(const CoroutineBodyStmt *S) { + VisitStmt(S); +} + +void StmtProfiler::VisitCoreturnStmt(const CoreturnStmt *S) { + VisitStmt(S); +} + +void StmtProfiler::VisitCoawaitExpr(const CoawaitExpr *S) { + VisitExpr(S); +} + +void StmtProfiler::VisitCoyieldExpr(const CoyieldExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) { VisitExpr(E); } diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index f8b73cb..e9edb0d 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -53,7 +53,7 @@ static void printIntegral(const TemplateArgument &TemplArg, } } - if (T->isBooleanType()) { + if (T->isBooleanType() && !Policy.MSVCFormatting) { Out << (Val.getBoolValue() ? "true" : "false"); } else if (T->isCharType()) { const char Ch = Val.getZExtValue(); @@ -88,15 +88,13 @@ TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, Integer.Type = Type.getAsOpaquePtr(); } -TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context, - const TemplateArgument *Args, - unsigned NumArgs) { - if (NumArgs == 0) +TemplateArgument +TemplateArgument::CreatePackCopy(ASTContext &Context, + ArrayRef<TemplateArgument> Args) { + if (Args.empty()) return getEmptyPack(); - - TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs]; - std::copy(Args, Args + NumArgs, Storage); - return TemplateArgument(Storage, NumArgs); + + return TemplateArgument(Args.copy(Context)); } bool TemplateArgument::isDependent() const { @@ -522,94 +520,67 @@ 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()); + std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size()); void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>()); - ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo(); - TAI->initializeFrom(List); - return TAI; + return new (Mem) ASTTemplateArgumentListInfo(List); } -void ASTTemplateArgumentListInfo::initializeFrom( - const TemplateArgumentListInfo &Info) { +ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( + const TemplateArgumentListInfo &Info) { LAngleLoc = Info.getLAngleLoc(); RAngleLoc = Info.getRAngleLoc(); NumTemplateArgs = Info.size(); - TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); + TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>(); for (unsigned i = 0; i != NumTemplateArgs; ++i) new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); } -void ASTTemplateArgumentListInfo::initializeFrom( - const TemplateArgumentListInfo &Info, - bool &Dependent, - bool &InstantiationDependent, - bool &ContainsUnexpandedParameterPack) { +void ASTTemplateKWAndArgsInfo::initializeFrom( + SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, + TemplateArgumentLoc *OutArgArray) { + this->TemplateKWLoc = TemplateKWLoc; + LAngleLoc = Info.getLAngleLoc(); + RAngleLoc = Info.getRAngleLoc(); + NumTemplateArgs = Info.size(); + + for (unsigned i = 0; i != NumTemplateArgs; ++i) + new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); +} + +void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) { + assert(TemplateKWLoc.isValid()); + LAngleLoc = SourceLocation(); + RAngleLoc = SourceLocation(); + this->TemplateKWLoc = TemplateKWLoc; + NumTemplateArgs = 0; +} + +void ASTTemplateKWAndArgsInfo::initializeFrom( + SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, + TemplateArgumentLoc *OutArgArray, bool &Dependent, + bool &InstantiationDependent, bool &ContainsUnexpandedParameterPack) { + this->TemplateKWLoc = TemplateKWLoc; LAngleLoc = Info.getLAngleLoc(); RAngleLoc = Info.getRAngleLoc(); NumTemplateArgs = Info.size(); - TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); for (unsigned i = 0; i != NumTemplateArgs; ++i) { Dependent = Dependent || Info[i].getArgument().isDependent(); - InstantiationDependent = InstantiationDependent || + InstantiationDependent = InstantiationDependent || Info[i].getArgument().isInstantiationDependent(); - ContainsUnexpandedParameterPack - = ContainsUnexpandedParameterPack || + ContainsUnexpandedParameterPack = + ContainsUnexpandedParameterPack || Info[i].getArgument().containsUnexpandedParameterPack(); - new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); + new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); } } -void ASTTemplateArgumentListInfo::copyInto( - TemplateArgumentListInfo &Info) const { +void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray, + TemplateArgumentListInfo &Info) const { Info.setLAngleLoc(LAngleLoc); Info.setRAngleLoc(RAngleLoc); for (unsigned I = 0; I != NumTemplateArgs; ++I) - Info.addArgument(getTemplateArgs()[I]); -} - -std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) { - return sizeof(ASTTemplateArgumentListInfo) + - sizeof(TemplateArgumentLoc) * NumTemplateArgs; -} - -void -ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc, - const TemplateArgumentListInfo &Info) { - Base::initializeFrom(Info); - setTemplateKeywordLoc(TemplateKWLoc); -} - -void -ASTTemplateKWAndArgsInfo -::initializeFrom(SourceLocation TemplateKWLoc, - const TemplateArgumentListInfo &Info, - bool &Dependent, - bool &InstantiationDependent, - bool &ContainsUnexpandedParameterPack) { - Base::initializeFrom(Info, Dependent, InstantiationDependent, - ContainsUnexpandedParameterPack); - setTemplateKeywordLoc(TemplateKWLoc); -} - -void -ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) { - // No explicit template arguments, but template keyword loc is valid. - assert(TemplateKWLoc.isValid()); - LAngleLoc = SourceLocation(); - RAngleLoc = SourceLocation(); - NumTemplateArgs = 0; - setTemplateKeywordLoc(TemplateKWLoc); -} - -std::size_t -ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) { - // Add space for the template keyword location. - // FIXME: There's room for this in the padding before the template args in - // 64-bit builds. - return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation); + Info.addArgument(ArgArray[I]); } diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp index 77c8fd5..47e0255 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp @@ -24,7 +24,7 @@ using namespace llvm; TemplateArgument SubstTemplateTemplateParmPackStorage::getArgumentPack() const { - return TemplateArgument(Arguments, size()); + return TemplateArgument(llvm::makeArrayRef(Arguments, size())); } void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { @@ -40,7 +40,7 @@ void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID, void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) { - Profile(ID, Context, Parameter, TemplateArgument(Arguments, size())); + Profile(ID, Context, Parameter, getArgumentPack()); } void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, @@ -51,6 +51,22 @@ void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, ArgPack.Profile(ID, Context); } +TemplateName::TemplateName(void *Ptr) { + Storage = StorageType::getFromOpaqueValue(Ptr); +} + +TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {} +TemplateName::TemplateName(OverloadedTemplateStorage *Storage) + : Storage(Storage) {} +TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage) + : Storage(Storage) {} +TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage) + : Storage(Storage) {} +TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {} +TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {} + +bool TemplateName::isNull() const { return Storage.isNull(); } + TemplateName::NameKind TemplateName::getKind() const { if (Storage.is<TemplateDecl *>()) return Template; @@ -81,6 +97,40 @@ TemplateDecl *TemplateName::getAsTemplateDecl() const { return nullptr; } +OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const { + if (UncommonTemplateNameStorage *Uncommon = + Storage.dyn_cast<UncommonTemplateNameStorage *>()) + return Uncommon->getAsOverloadedStorage(); + + return nullptr; +} + +SubstTemplateTemplateParmStorage * +TemplateName::getAsSubstTemplateTemplateParm() const { + if (UncommonTemplateNameStorage *uncommon = + Storage.dyn_cast<UncommonTemplateNameStorage *>()) + return uncommon->getAsSubstTemplateTemplateParm(); + + return nullptr; +} + +SubstTemplateTemplateParmPackStorage * +TemplateName::getAsSubstTemplateTemplateParmPack() const { + if (UncommonTemplateNameStorage *Uncommon = + Storage.dyn_cast<UncommonTemplateNameStorage *>()) + return Uncommon->getAsSubstTemplateTemplateParmPack(); + + return nullptr; +} + +QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const { + return Storage.dyn_cast<QualifiedTemplateName *>(); +} + +DependentTemplateName *TemplateName::getAsDependentTemplateName() const { + return Storage.dyn_cast<DependentTemplateName *>(); +} + bool TemplateName::isDependent() const { if (TemplateDecl *Template = getAsTemplateDecl()) { if (isa<TemplateTemplateParmDecl>(Template)) diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index cee5fee..b467dac 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -22,6 +22,7 @@ #include "clang/AST/Type.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetInfo.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" @@ -509,6 +510,28 @@ bool Type::isObjCClassOrClassKindOfType() const { return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType(); } +/// Was this type written with the special inert-in-MRC __unsafe_unretained +/// qualifier? +/// +/// This approximates the answer to the following question: if this +/// translation unit were compiled in ARC, would this type be qualified +/// with __unsafe_unretained? +bool Type::isObjCInertUnsafeUnretainedType() const { + const Type *cur = this; + while (true) { + if (auto attributed = dyn_cast<AttributedType>(cur)) { + if (attributed->getAttrKind() == + AttributedType::attr_objc_inert_unsafe_unretained) + return true; + } + + // Single-step desugar until we run out of sugar. + QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType(); + if (next.getTypePtr() == cur) return false; + cur = next.getTypePtr(); + } +} + ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, @@ -836,11 +859,8 @@ public: } if (exceptionChanged) { - unsigned size = sizeof(QualType) * exceptionTypes.size(); - void *mem = Ctx.Allocate(size, llvm::alignOf<QualType>()); - memcpy(mem, exceptionTypes.data(), size); - info.ExceptionSpec.Exceptions - = llvm::makeArrayRef((QualType *)mem, exceptionTypes.size()); + info.ExceptionSpec.Exceptions = + llvm::makeArrayRef(exceptionTypes).copy(Ctx); } } @@ -950,7 +970,7 @@ public: == T->getDeducedType().getAsOpaquePtr()) return QualType(T, 0); - return Ctx.getAutoType(deducedType, T->isDecltypeAuto(), + return Ctx.getAutoType(deducedType, T->getKeyword(), T->isDependentType()); } @@ -1158,11 +1178,8 @@ QualType QualType::substObjCTypeArgs( } if (exceptionChanged) { - unsigned size = sizeof(QualType) * exceptionTypes.size(); - void *mem = ctx.Allocate(size, llvm::alignOf<QualType>()); - memcpy(mem, exceptionTypes.data(), size); - info.ExceptionSpec.Exceptions - = llvm::makeArrayRef((QualType *)mem, exceptionTypes.size()); + info.ExceptionSpec.Exceptions = + llvm::makeArrayRef(exceptionTypes).copy(ctx); } } @@ -1275,7 +1292,7 @@ Optional<ArrayRef<QualType>> Type::getObjCSubstitutions( if (!dcTypeParams) return None; } else { - // If we are in neither a class mor a category, there's no + // If we are in neither a class nor a category, there's no // substitution to perform. dcCategoryDecl = dyn_cast<ObjCCategoryDecl>(dc); if (!dcCategoryDecl) @@ -1905,6 +1922,28 @@ bool Type::isIncompleteType(NamedDecl **Def) const { case IncompleteArray: // An array of unknown size is an incomplete type (C99 6.2.5p22). return true; + case MemberPointer: { + // Member pointers in the MS ABI have special behavior in + // RequireCompleteType: they attach a MSInheritanceAttr to the CXXRecordDecl + // to indicate which inheritance model to use. + auto *MPTy = cast<MemberPointerType>(CanonicalType); + const Type *ClassTy = MPTy->getClass(); + // Member pointers with dependent class types don't get special treatment. + if (ClassTy->isDependentType()) + return false; + const CXXRecordDecl *RD = ClassTy->getAsCXXRecordDecl(); + ASTContext &Context = RD->getASTContext(); + // Member pointers not in the MS ABI don't get special treatment. + if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) + return false; + // The inheritance attribute might only be present on the most recent + // CXXRecordDecl, use that one. + RD = RD->getMostRecentDecl(); + // Nothing interesting to do if the inheritance attribute is already set. + if (RD->hasAttr<MSInheritanceAttr>()) + return false; + return true; + } case ObjCObject: return cast<ObjCObjectType>(CanonicalType)->getBaseType() ->isIncompleteType(Def); @@ -2260,7 +2299,7 @@ bool QualType::isCXX11PODType(ASTContext &Context) const { // a standard-layout class, and has no non-static data members of type // non-POD struct, non-POD union (or array of such types). [...] // - // We don't directly query the recursive aspect as the requiremets for + // We don't directly query the recursive aspect as the requirements for // both standard-layout classes and trivial classes apply recursively // already. } @@ -2473,51 +2512,115 @@ const char *Type::getTypeClassName() const { StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { switch (getKind()) { - case Void: return "void"; - case Bool: return Policy.Bool ? "bool" : "_Bool"; - case Char_S: return "char"; - case Char_U: return "char"; - case SChar: return "signed char"; - case Short: return "short"; - case Int: return "int"; - case Long: return "long"; - case LongLong: return "long long"; - case Int128: return "__int128"; - case UChar: return "unsigned char"; - case UShort: return "unsigned short"; - case UInt: return "unsigned int"; - case ULong: return "unsigned long"; - case ULongLong: return "unsigned long long"; - case UInt128: return "unsigned __int128"; - case Half: return Policy.Half ? "half" : "__fp16"; - case Float: return "float"; - case Double: return "double"; - case LongDouble: return "long double"; + case Void: + return "void"; + case Bool: + return Policy.Bool ? "bool" : "_Bool"; + case Char_S: + return "char"; + case Char_U: + return "char"; + case SChar: + return "signed char"; + case Short: + return "short"; + case Int: + return "int"; + case Long: + return "long"; + case LongLong: + return "long long"; + case Int128: + return "__int128"; + case UChar: + return "unsigned char"; + case UShort: + return "unsigned short"; + case UInt: + return "unsigned int"; + case ULong: + return "unsigned long"; + case ULongLong: + return "unsigned long long"; + case UInt128: + return "unsigned __int128"; + case Half: + return Policy.Half ? "half" : "__fp16"; + case Float: + return "float"; + case Double: + return "double"; + case LongDouble: + return "long double"; case WChar_S: - case WChar_U: return Policy.MSWChar ? "__wchar_t" : "wchar_t"; - case Char16: return "char16_t"; - case Char32: return "char32_t"; - case NullPtr: return "nullptr_t"; - case Overload: return "<overloaded function type>"; - case BoundMember: return "<bound member function type>"; - case PseudoObject: return "<pseudo-object type>"; - case Dependent: return "<dependent type>"; - case UnknownAny: return "<unknown type>"; - case ARCUnbridgedCast: return "<ARC unbridged cast type>"; - case BuiltinFn: return "<builtin fn type>"; - case ObjCId: return "id"; - case ObjCClass: return "Class"; - case ObjCSel: return "SEL"; - case OCLImage1d: return "image1d_t"; - case OCLImage1dArray: return "image1d_array_t"; - case OCLImage1dBuffer: return "image1d_buffer_t"; - case OCLImage2d: return "image2d_t"; - case OCLImage2dArray: return "image2d_array_t"; - case OCLImage3d: return "image3d_t"; - case OCLSampler: return "sampler_t"; - case OCLEvent: return "event_t"; + case WChar_U: + return Policy.MSWChar ? "__wchar_t" : "wchar_t"; + case Char16: + return "char16_t"; + case Char32: + return "char32_t"; + case NullPtr: + return "nullptr_t"; + case Overload: + return "<overloaded function type>"; + case BoundMember: + return "<bound member function type>"; + case PseudoObject: + return "<pseudo-object type>"; + case Dependent: + return "<dependent type>"; + case UnknownAny: + return "<unknown type>"; + case ARCUnbridgedCast: + return "<ARC unbridged cast type>"; + case BuiltinFn: + return "<builtin fn type>"; + case ObjCId: + return "id"; + case ObjCClass: + return "Class"; + case ObjCSel: + return "SEL"; + case OCLImage1d: + return "image1d_t"; + case OCLImage1dArray: + return "image1d_array_t"; + case OCLImage1dBuffer: + return "image1d_buffer_t"; + case OCLImage2d: + return "image2d_t"; + case OCLImage2dArray: + return "image2d_array_t"; + case OCLImage2dDepth: + return "image2d_depth_t"; + case OCLImage2dArrayDepth: + return "image2d_array_depth_t"; + case OCLImage2dMSAA: + return "image2d_msaa_t"; + case OCLImage2dArrayMSAA: + return "image2d_array_msaa_t"; + case OCLImage2dMSAADepth: + return "image2d_msaa_depth_t"; + case OCLImage2dArrayMSAADepth: + return "image2d_array_msaa_depth_t"; + case OCLImage3d: + return "image3d_t"; + case OCLSampler: + return "sampler_t"; + case OCLEvent: + return "event_t"; + case OCLClkEvent: + return "clk_event_t"; + case OCLQueue: + return "queue_t"; + case OCLNDRange: + return "ndrange_t"; + case OCLReserveID: + return "reserve_id_t"; + case OMPArraySection: + return "<OpenMP array section type>"; } - + llvm_unreachable("Invalid builtin type."); } @@ -2863,6 +2966,48 @@ bool TagType::isBeingDefined() const { return getDecl()->isBeingDefined(); } +bool AttributedType::isQualifier() const { + switch (getAttrKind()) { + // These are type qualifiers in the traditional C sense: they annotate + // something about a specific value/variable of a type. (They aren't + // always part of the canonical type, though.) + case AttributedType::attr_address_space: + case AttributedType::attr_objc_gc: + case AttributedType::attr_objc_ownership: + case AttributedType::attr_objc_inert_unsafe_unretained: + case AttributedType::attr_nonnull: + case AttributedType::attr_nullable: + case AttributedType::attr_null_unspecified: + return true; + + // These aren't qualifiers; they rewrite the modified type to be a + // semantically different type. + case AttributedType::attr_regparm: + case AttributedType::attr_vector_size: + case AttributedType::attr_neon_vector_type: + case AttributedType::attr_neon_polyvector_type: + case AttributedType::attr_pcs: + case AttributedType::attr_pcs_vfp: + case AttributedType::attr_noreturn: + case AttributedType::attr_cdecl: + case AttributedType::attr_fastcall: + case AttributedType::attr_stdcall: + case AttributedType::attr_thiscall: + case AttributedType::attr_pascal: + case AttributedType::attr_vectorcall: + case AttributedType::attr_inteloclbicc: + case AttributedType::attr_ms_abi: + case AttributedType::attr_sysv_abi: + case AttributedType::attr_ptr32: + case AttributedType::attr_ptr64: + case AttributedType::attr_sptr: + case AttributedType::attr_uptr: + case AttributedType::attr_objc_kindof: + return false; + } + llvm_unreachable("bad attributed type kind"); +} + bool AttributedType::isMSTypeSpec() const { switch (getAttrKind()) { default: return false; @@ -2888,6 +3033,7 @@ bool AttributedType::isCallingConv() const { case attr_neon_polyvector_type: case attr_objc_gc: case attr_objc_ownership: + case attr_objc_inert_unsafe_unretained: case attr_noreturn: case attr_nonnull: case attr_nullable: @@ -2930,7 +3076,7 @@ SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, } TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const { - return TemplateArgument(Arguments, NumArguments); + return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments)); } void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) { @@ -3215,6 +3361,8 @@ static CachedProperties computeCachedProperties(const Type *T) { return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType()); case Type::Atomic: return Cache::get(cast<AtomicType>(T)->getValueType()); + case Type::Pipe: + return Cache::get(cast<PipeType>(T)->getElementType()); } llvm_unreachable("unhandled type class"); @@ -3297,6 +3445,8 @@ static LinkageInfo computeLinkageInfo(const Type *T) { return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType()); case Type::Atomic: return computeLinkageInfo(cast<AtomicType>(T)->getValueType()); + case Type::Pipe: + return computeLinkageInfo(cast<PipeType>(T)->getElementType()); } llvm_unreachable("unhandled type class"); @@ -3416,11 +3566,22 @@ bool Type::canHaveNullability() const { case BuiltinType::OCLImage1dBuffer: case BuiltinType::OCLImage2d: case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage2dDepth: + case BuiltinType::OCLImage2dArrayDepth: + case BuiltinType::OCLImage2dMSAA: + case BuiltinType::OCLImage2dArrayMSAA: + case BuiltinType::OCLImage2dMSAADepth: + case BuiltinType::OCLImage2dArrayMSAADepth: case BuiltinType::OCLImage3d: case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: + case BuiltinType::OCLClkEvent: + case BuiltinType::OCLQueue: + case BuiltinType::OCLNDRange: + case BuiltinType::OCLReserveID: case BuiltinType::BuiltinFn: case BuiltinType::NullPtr: + case BuiltinType::OMPArraySection: return false; } @@ -3444,6 +3605,7 @@ bool Type::canHaveNullability() const { case Type::ObjCObject: case Type::ObjCInterface: case Type::Atomic: + case Type::Pipe: return false; } llvm_unreachable("bad type kind!"); @@ -3521,7 +3683,7 @@ bool Type::isObjCARCImplicitlyUnretainedType() const { if (const ObjCObjectPointerType *opt = dyn_cast<ObjCObjectPointerType>(canon)) { - // Class and Class<Protocol> don't require retension. + // Class and Class<Protocol> don't require retention. if (opt->getObjectType()->isObjCClass()) return true; } diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp index 85bda6a..d08b07b 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp @@ -192,7 +192,7 @@ SourceLocation TypeLoc::getBeginLoc() const { Cur = Cur.getNextTypeLoc(); continue; default: - if (!Cur.getLocalSourceRange().getBegin().isInvalid()) + if (Cur.getLocalSourceRange().getBegin().isValid()) LeftMost = Cur; Cur = Cur.getNextTypeLoc(); if (Cur.isNull()) @@ -338,10 +338,21 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::OCLImage1dBuffer: case BuiltinType::OCLImage2d: case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage2dDepth: + case BuiltinType::OCLImage2dArrayDepth: + case BuiltinType::OCLImage2dMSAA: + case BuiltinType::OCLImage2dArrayMSAA: + case BuiltinType::OCLImage2dMSAADepth: + case BuiltinType::OCLImage2dArrayMSAADepth: case BuiltinType::OCLImage3d: case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: + case BuiltinType::OCLClkEvent: + case BuiltinType::OCLQueue: + case BuiltinType::OCLNDRange: + case BuiltinType::OCLReserveID: case BuiltinType::BuiltinFn: + case BuiltinType::OMPArraySection: return TST_unspecified; } @@ -365,6 +376,27 @@ SourceLocation TypeLoc::findNullabilityLoc() const { return SourceLocation(); } +TypeLoc TypeLoc::findExplicitQualifierLoc() const { + // Qualified types. + if (auto qual = getAs<QualifiedTypeLoc>()) + return qual; + + TypeLoc loc = IgnoreParens(); + + // Attributed types. + if (auto attr = loc.getAs<AttributedTypeLoc>()) { + if (attr.isQualifier()) return attr; + return attr.getModifiedLoc().findExplicitQualifierLoc(); + } + + // C11 _Atomic types. + if (auto atomic = loc.getAs<AtomicTypeLoc>()) { + return atomic; + } + + return TypeLoc(); +} + void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { setHasBaseTypeAsWritten(true); diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index 0bb50c6..b202523 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -193,6 +193,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::ObjCObject: case Type::ObjCInterface: case Type::Atomic: + case Type::Pipe: CanPrefixQualifiers = true; break; @@ -835,7 +836,11 @@ void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) { if (!T->getDeducedType().isNull()) { printBefore(T->getDeducedType(), OS); } else { - OS << (T->isDecltypeAuto() ? "decltype(auto)" : "auto"); + switch (T->getKeyword()) { + case AutoTypeKeyword::Auto: OS << "auto"; break; + case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break; + case AutoTypeKeyword::GNUAutoType: OS << "__auto_type"; break; + } spaceBeforePlaceHolder(OS); } } @@ -855,6 +860,15 @@ void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) { } void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { } +void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) { + IncludeStrongLifetimeRAII Strong(Policy); + + OS << "pipe"; + spaceBeforePlaceHolder(OS); +} + +void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) { +} /// Appends the given scope to the end of a string. void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) { if (DC->isTranslationUnit()) return; @@ -921,12 +935,13 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { } else { // Make an unambiguous representation for anonymous types, e.g. // (anonymous enum at /usr/include/string.h:120:9) - + OS << (Policy.MSVCFormatting ? '`' : '('); + if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) { - OS << "(lambda"; + OS << "lambda"; HasKindDecoration = true; } else { - OS << "(anonymous"; + OS << "anonymous"; } if (Policy.AnonymousTagLocations) { @@ -944,8 +959,8 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { << ':' << PLoc.getColumn(); } } - - OS << ')'; + + OS << (Policy.MSVCFormatting ? '\'' : ')'); } // If this is a class template specialization, print the template @@ -1187,6 +1202,10 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, printAfter(T->getModifiedType(), OS); + // Don't print the inert __unsafe_unretained attribute at all. + if (T->getAttrKind() == AttributedType::attr_objc_inert_unsafe_unretained) + return; + // Print nullability type specifiers that occur after if (T->getAttrKind() == AttributedType::attr_nonnull || T->getAttrKind() == AttributedType::attr_nullable || @@ -1393,6 +1412,7 @@ TemplateSpecializationType::PrintTemplateArgumentList( unsigned NumArgs, const PrintingPolicy &Policy, bool SkipBrackets) { + const char *Comma = Policy.MSVCFormatting ? "," : ", "; if (!SkipBrackets) OS << '<'; @@ -1403,14 +1423,14 @@ TemplateSpecializationType::PrintTemplateArgumentList( llvm::raw_svector_ostream ArgOS(Buf); if (Args[Arg].getKind() == TemplateArgument::Pack) { if (Args[Arg].pack_size() && Arg > 0) - OS << ", "; + OS << Comma; PrintTemplateArgumentList(ArgOS, Args[Arg].pack_begin(), Args[Arg].pack_size(), Policy, true); } else { if (Arg > 0) - OS << ", "; + OS << Comma; Args[Arg].print(Policy, ArgOS); } StringRef ArgString = ArgOS.str(); @@ -1442,11 +1462,12 @@ PrintTemplateArgumentList(raw_ostream &OS, const TemplateArgumentLoc *Args, unsigned NumArgs, const PrintingPolicy &Policy) { OS << '<'; + const char *Comma = Policy.MSVCFormatting ? "," : ", "; bool needSpace = false; for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { if (Arg > 0) - OS << ", "; + OS << Comma; // Print the argument into a string. SmallString<128> Buf; diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp index ca5f0aa..bae0186 100644 --- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp @@ -177,14 +177,12 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, CXXFinalOverriderMap FinalOverriders; MostDerivedClass->getFinalOverriders(FinalOverriders); - for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(), - E = FinalOverriders.end(); I != E; ++I) { - const CXXMethodDecl *MD = I->first; - const OverridingMethods& Methods = I->second; - - for (OverridingMethods::const_iterator I = Methods.begin(), - E = Methods.end(); I != E; ++I) { - unsigned SubobjectNumber = I->first; + for (const auto &Overrider : FinalOverriders) { + const CXXMethodDecl *MD = Overrider.first; + const OverridingMethods &Methods = Overrider.second; + + for (const auto &M : Methods) { + unsigned SubobjectNumber = M.first; assert(SubobjectOffsets.count(std::make_pair(MD->getParent(), SubobjectNumber)) && "Did not find subobject offset!"); @@ -192,8 +190,8 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, CharUnits BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(), SubobjectNumber)]; - assert(I->second.size() == 1 && "Final overrider is not unique!"); - const UniqueVirtualMethod &Method = I->second.front(); + assert(M.second.size() == 1 && "Final overrider is not unique!"); + const UniqueVirtualMethod &Method = M.second.front(); const CXXRecordDecl *OverriderRD = Method.Method->getParent(); assert(SubobjectLayoutClassOffsets.count( @@ -482,13 +480,9 @@ static bool HasSameVirtualSignature(const CXXMethodDecl *LHS, // Force the signatures to match. We can't rely on the overrides // list here because there isn't necessarily an inheritance // relationship between the two methods. - if (LT->getTypeQuals() != RT->getTypeQuals() || - LT->getNumParams() != RT->getNumParams()) + if (LT->getTypeQuals() != RT->getTypeQuals()) return false; - for (unsigned I = 0, E = LT->getNumParams(); I != E; ++I) - if (LT->getParamType(I) != RT->getParamType(I)) - return false; - return true; + return LT->getParamTypes() == RT->getParamTypes(); } bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS, @@ -515,8 +509,8 @@ bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS, bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD, CharUnits OffsetOffset) { // Check if we can reuse an offset. - for (unsigned I = 0, E = Offsets.size(); I != E; ++I) { - if (MethodsCanShareVCallOffset(Offsets[I].first, MD)) + for (const auto &OffsetPair : Offsets) { + if (MethodsCanShareVCallOffset(OffsetPair.first, MD)) return false; } @@ -527,9 +521,9 @@ bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD, CharUnits VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) { // Look for an offset. - for (unsigned I = 0, E = Offsets.size(); I != E; ++I) { - if (MethodsCanShareVCallOffset(Offsets[I].first, MD)) - return Offsets[I].second; + for (const auto &OffsetPair : Offsets) { + if (MethodsCanShareVCallOffset(OffsetPair.first, MD)) + return OffsetPair.second; } llvm_unreachable("Should always find a vcall offset offset!"); @@ -1097,39 +1091,30 @@ visitAllOverriddenMethods(const CXXMethodDecl *MD, VisitorTy &Visitor) { for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), E = MD->end_overridden_methods(); I != E; ++I) { const CXXMethodDecl *OverriddenMD = *I; - if (!Visitor.visit(OverriddenMD)) + if (!Visitor(OverriddenMD)) continue; visitAllOverriddenMethods(OverriddenMD, Visitor); } } -namespace { - struct OverriddenMethodsCollector { - OverriddenMethodsSetTy *Methods; - - bool visit(const CXXMethodDecl *MD) { - // Don't recurse on this method if we've already collected it. - return Methods->insert(MD).second; - } - }; -} - /// ComputeAllOverriddenMethods - Given a method decl, will return a set of all /// the overridden methods that the function decl overrides. static void ComputeAllOverriddenMethods(const CXXMethodDecl *MD, OverriddenMethodsSetTy& OverriddenMethods) { - OverriddenMethodsCollector Collector = { &OverriddenMethods }; - visitAllOverriddenMethods(MD, Collector); + auto OverriddenMethodsCollector = [&](const CXXMethodDecl *MD) { + // Don't recurse on this method if we've already collected it. + return OverriddenMethods.insert(MD).second; + }; + visitAllOverriddenMethods(MD, OverriddenMethodsCollector); } void ItaniumVTableBuilder::ComputeThisAdjustments() { // Now go through the method info map and see if any of the methods need // 'this' pointer adjustments. - for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(), - E = MethodInfoMap.end(); I != E; ++I) { - const CXXMethodDecl *MD = I->first; - const MethodInfo &MethodInfo = I->second; + for (const auto &MI : MethodInfoMap) { + const CXXMethodDecl *MD = MI.first; + const MethodInfo &MethodInfo = MI.second; // Ignore adjustments for unused function pointers. uint64_t VTableIndex = MethodInfo.VTableIndex; @@ -1175,10 +1160,9 @@ void ItaniumVTableBuilder::ComputeThisAdjustments() { return; } - for (VTableThunksMapTy::const_iterator I = VTableThunks.begin(), - E = VTableThunks.end(); I != E; ++I) { - const VTableComponent &Component = Components[I->first]; - const ThunkInfo &Thunk = I->second; + for (const auto &TI : VTableThunks) { + const VTableComponent &Component = Components[TI.first]; + const ThunkInfo &Thunk = TI.second; const CXXMethodDecl *MD; switch (Component.getKind()) { @@ -1237,10 +1221,9 @@ BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset( // We have to go through all the paths, and see which one leads us to the // right base subobject. - for (CXXBasePaths::const_paths_iterator I = Paths.begin(), E = Paths.end(); - I != E; ++I) { - BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, *I); - + for (const CXXBasePath &Path : Paths) { + BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path); + CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset; if (Offset.VirtualBase) { @@ -1440,15 +1423,11 @@ FindNearestOverriddenMethod(const CXXMethodDecl *MD, BasesSetVectorTy &Bases) { OverriddenMethodsSetTy OverriddenMethods; ComputeAllOverriddenMethods(MD, OverriddenMethods); - - for (int I = Bases.size(), E = 0; I != E; --I) { - const CXXRecordDecl *PrimaryBase = Bases[I - 1]; + for (const CXXRecordDecl *PrimaryBase : + llvm::make_range(Bases.rbegin(), Bases.rend())) { // Now check the overridden methods. - for (OverriddenMethodsSetTy::const_iterator I = OverriddenMethods.begin(), - E = OverriddenMethods.end(); I != E; ++I) { - const CXXMethodDecl *OverriddenMD = *I; - + for (const CXXMethodDecl *OverriddenMD : OverriddenMethods) { // We found our overridden method. if (OverriddenMD->getParent() == PrimaryBase) return OverriddenMD; @@ -1596,10 +1575,7 @@ void ItaniumVTableBuilder::AddMethods( if (ImplicitVirtualDtor) NewVirtualFunctions.push_back(ImplicitVirtualDtor); - for (NewVirtualFunctionsTy::const_iterator I = NewVirtualFunctions.begin(), - E = NewVirtualFunctions.end(); I != E; ++I) { - const CXXMethodDecl *MD = *I; - + for (const CXXMethodDecl *MD : NewVirtualFunctions) { // Get the final overrider. FinalOverriders::OverriderInfo Overrider = Overriders.getOverrider(MD, Base.getBaseOffset()); @@ -1700,10 +1676,9 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables( const CXXRecordDecl *RD = Base.getBase(); if (RD == MostDerivedClass) { assert(MethodVTableIndices.empty()); - for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(), - E = MethodInfoMap.end(); I != E; ++I) { - const CXXMethodDecl *MD = I->first; - const MethodInfo &MI = I->second; + for (const auto &I : MethodInfoMap) { + const CXXMethodDecl *MD = I.first; + const MethodInfo &MI = I.second; if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = MI.VTableIndex - AddressPoint; @@ -1924,11 +1899,10 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { // Since an address point can be shared by multiple subobjects, we use an // STL multimap. std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex; - for (AddressPointsMapTy::const_iterator I = AddressPoints.begin(), - E = AddressPoints.end(); I != E; ++I) { - const BaseSubobject& Base = I->first; - uint64_t Index = I->second; - + for (const auto &AP : AddressPoints) { + const BaseSubobject &Base = AP.first; + uint64_t Index = AP.second; + AddressPointsByIndex.insert(std::make_pair(Index, Base)); } @@ -2077,18 +2051,16 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { // We store the class names in a set to get a stable order. std::set<std::string> ClassNames; - for (std::multimap<uint64_t, BaseSubobject>::const_iterator I = - AddressPointsByIndex.lower_bound(NextIndex), E = - AddressPointsByIndex.upper_bound(NextIndex); I != E; ++I) { - assert(I->second.getBaseOffset() == BaseOffset && + for (const auto &I : + llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) { + assert(I.second.getBaseOffset() == BaseOffset && "Invalid base offset!"); - const CXXRecordDecl *RD = I->second.getBase(); + const CXXRecordDecl *RD = I.second.getBase(); ClassNames.insert(RD->getQualifiedNameAsString()); } - - for (std::set<std::string>::const_iterator I = ClassNames.begin(), - E = ClassNames.end(); I != E; ++I) { - Out << " -- (" << *I; + + for (const std::string &Name : ClassNames) { + Out << " -- (" << Name; Out << ", " << BaseOffset.getQuantity() << ") vtable address --\n"; } } @@ -2105,12 +2077,10 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { // a stable order. std::map<std::string, CharUnits> ClassNamesAndOffsets; - for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(), - E = VBaseOffsetOffsets.end(); I != E; ++I) { - std::string ClassName = I->first->getQualifiedNameAsString(); - CharUnits OffsetOffset = I->second; - ClassNamesAndOffsets.insert( - std::make_pair(ClassName, OffsetOffset)); + for (const auto &I : VBaseOffsetOffsets) { + std::string ClassName = I.first->getQualifiedNameAsString(); + CharUnits OffsetOffset = I.second; + ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset)); } Out << "Virtual base offset offsets for '"; @@ -2119,10 +2089,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { Out << ClassNamesAndOffsets.size(); Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n"; - for (std::map<std::string, CharUnits>::const_iterator I = - ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end(); - I != E; ++I) - Out << " " << I->first << " | " << I->second.getQuantity() << '\n'; + for (const auto &I : ClassNamesAndOffsets) + Out << " " << I.first << " | " << I.second.getQuantity() << '\n'; Out << "\n"; } @@ -2130,10 +2098,9 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { if (!Thunks.empty()) { // We store the method names in a map to get a stable order. std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls; - - for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end(); - I != E; ++I) { - const CXXMethodDecl *MD = I->first; + + for (const auto &I : Thunks) { + const CXXMethodDecl *MD = I.first; std::string MethodName = PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual, MD); @@ -2141,11 +2108,9 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { MethodNamesAndDecls.insert(std::make_pair(MethodName, MD)); } - for (std::map<std::string, const CXXMethodDecl *>::const_iterator I = - MethodNamesAndDecls.begin(), E = MethodNamesAndDecls.end(); - I != E; ++I) { - const std::string &MethodName = I->first; - const CXXMethodDecl *MD = I->second; + for (const auto &I : MethodNamesAndDecls) { + const std::string &MethodName = I.first; + const CXXMethodDecl *MD = I.second; ThunkInfoVectorTy ThunksVector = Thunks[MD]; std::sort(ThunksVector.begin(), ThunksVector.end(), @@ -2225,10 +2190,9 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { MostDerivedClass->printQualifiedName(Out); Out << "' (" << IndicesMap.size() << " entries).\n"; - for (std::map<uint64_t, std::string>::const_iterator I = IndicesMap.begin(), - E = IndicesMap.end(); I != E; ++I) { - uint64_t VTableIndex = I->first; - const std::string &MethodName = I->second; + for (const auto &I : IndicesMap) { + uint64_t VTableIndex = I.first; + const std::string &MethodName = I.second; Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName << '\n'; @@ -2303,14 +2267,11 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, /*BaseIsVirtual=*/false, /*OffsetInLayoutClass=*/CharUnits::Zero()); - for (VCallAndVBaseOffsetBuilder::VBaseOffsetOffsetsMapTy::const_iterator I = - Builder.getVBaseOffsetOffsets().begin(), - E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) { + for (const auto &I : Builder.getVBaseOffsetOffsets()) { // Insert all types. - ClassPairTy ClassPair(RD, I->first); - - VirtualBaseClassOffsetOffsets.insert( - std::make_pair(ClassPair, I->second)); + ClassPairTy ClassPair(RD, I.first); + + VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second)); } I = VirtualBaseClassOffsetOffsets.find(ClassPair); @@ -2361,14 +2322,11 @@ ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) { if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase))) return; - for (ItaniumVTableBuilder::VBaseOffsetOffsetsMapTy::const_iterator - I = Builder.getVBaseOffsetOffsets().begin(), - E = Builder.getVBaseOffsetOffsets().end(); - I != E; ++I) { + for (const auto &I : Builder.getVBaseOffsetOffsets()) { // Insert all types. - ClassPairTy ClassPair(RD, I->first); - - VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second)); + ClassPairTy ClassPair(RD, I.first); + + VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second)); } } @@ -2561,10 +2519,9 @@ private: "vftable can't be empty"); assert(MethodVFTableLocations.empty()); - for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(), - E = MethodInfoMap.end(); I != E; ++I) { - const CXXMethodDecl *MD = I->first; - const MethodInfo &MI = I->second; + for (const auto &I : MethodInfoMap) { + const CXXMethodDecl *MD = I.first; + const MethodInfo &MI = I.second; // Skip the methods that the MostDerivedClass didn't override // and the entries shadowed by return adjusting thunks. if (MD->getParent() != MostDerivedClass || MI.Shadowed) @@ -2633,28 +2590,8 @@ public: void dumpLayout(raw_ostream &); }; -/// InitialOverriddenDefinitionCollector - Finds the set of least derived bases -/// that define the given method. -struct InitialOverriddenDefinitionCollector { - BasesSetVectorTy Bases; - OverriddenMethodsSetTy VisitedOverriddenMethods; - - bool visit(const CXXMethodDecl *OverriddenMD) { - if (OverriddenMD->size_overridden_methods() == 0) - Bases.insert(OverriddenMD->getParent()); - // Don't recurse on this method if we've already collected it. - return VisitedOverriddenMethods.insert(OverriddenMD).second; - } -}; - } // end namespace -static bool BaseInSet(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, void *BasesSet) { - BasesSetVectorTy *Bases = (BasesSetVectorTy *)BasesSet; - return Bases->count(Specifier->getType()->getAsCXXRecordDecl()); -} - // Let's study one class hierarchy as an example: // struct A { // virtual void f(); @@ -2711,17 +2648,33 @@ static bool BaseInSet(const CXXBaseSpecifier *Specifier, // for the given method, relative to the beginning of the MostDerivedClass. CharUnits VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) { - InitialOverriddenDefinitionCollector Collector; - visitAllOverriddenMethods(Overrider.Method, Collector); + BasesSetVectorTy Bases; + + { + // Find the set of least derived bases that define the given method. + OverriddenMethodsSetTy VisitedOverriddenMethods; + auto InitialOverriddenDefinitionCollector = [&]( + const CXXMethodDecl *OverriddenMD) { + if (OverriddenMD->size_overridden_methods() == 0) + Bases.insert(OverriddenMD->getParent()); + // Don't recurse on this method if we've already collected it. + return VisitedOverriddenMethods.insert(OverriddenMD).second; + }; + visitAllOverriddenMethods(Overrider.Method, + InitialOverriddenDefinitionCollector); + } // If there are no overrides then 'this' is located // in the base that defines the method. - if (Collector.Bases.size() == 0) + if (Bases.size() == 0) return Overrider.Offset; CXXBasePaths Paths; - Overrider.Method->getParent()->lookupInBases(BaseInSet, &Collector.Bases, - Paths); + Overrider.Method->getParent()->lookupInBases( + [&Bases](const CXXBaseSpecifier *Specifier, CXXBasePath &) { + return Bases.count(Specifier->getType()->getAsCXXRecordDecl()); + }, + 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 @@ -2732,17 +2685,14 @@ VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) { 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); + for (const CXXBasePath &Path : Paths) { CharUnits ThisOffset = Overrider.Offset; CharUnits LastVBaseOffset; // For each path from the overrider to the parents of the overridden // methods, traverse the path, calculating the this offset in the most // derived class. - for (int J = 0, F = Path.size(); J != F; ++J) { - const CXXBasePathElement &Element = Path[J]; + for (const CXXBasePathElement &Element : Path) { QualType CurTy = Element.Base->getType(); const CXXRecordDecl *PrevRD = Element.Class, *CurRD = CurTy->getAsCXXRecordDecl(); @@ -2932,26 +2882,30 @@ 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 and non-virtual methods). + // (including overrides, non-virtual methods and any other named decl that + // might be nested within the class). // 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 (const auto *MD : RD->methods()) { - MD = MD->getCanonicalDecl(); + for (const auto *D : RD->decls()) { + const auto *ND = dyn_cast<NamedDecl>(D); + if (!ND) + continue; VisitedGroupIndicesTy::iterator J; bool Inserted; std::tie(J, Inserted) = VisitedGroupIndices.insert( - std::make_pair(MD->getDeclName(), Groups.size())); + std::make_pair(ND->getDeclName(), Groups.size())); if (Inserted) Groups.push_back(MethodGroup()); - if (MD->isVirtual()) - Groups[J->second].push_back(MD); + if (const auto *MD = dyn_cast<CXXMethodDecl>(ND)) + if (MD->isVirtual()) + Groups[J->second].push_back(MD->getCanonicalDecl()); } - for (unsigned I = 0, E = Groups.size(); I != E; ++I) - VirtualMethods.append(Groups[I].rbegin(), Groups[I].rend()); + for (const MethodGroup &Group : Groups) + VirtualMethods.append(Group.rbegin(), Group.rend()); } static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD) { @@ -3011,9 +2965,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, // sub-bases; // - adding new slots for methods that require Return adjustment. // We keep track of the methods visited in the sub-bases in MethodInfoMap. - for (unsigned I = 0, E = VirtualMethods.size(); I != E; ++I) { - const CXXMethodDecl *MD = VirtualMethods[I]; - + for (const CXXMethodDecl *MD : VirtualMethods) { FinalOverriders::OverriderInfo FinalOverrider = Overriders.getOverrider(MD, Base.getBaseOffset()); const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method; @@ -3122,10 +3074,10 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth, } 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) { + for (const CXXRecordDecl *Elem : + llvm::make_range(Path.rbegin(), Path.rend())) { Out << "'"; - (*I)->printQualifiedName(Out); + Elem->printQualifiedName(Out); Out << "' in "; } } @@ -3247,21 +3199,17 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { // We store the method names in a map to get a stable order. std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls; - for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end(); - I != E; ++I) { - const CXXMethodDecl *MD = I->first; + for (const auto &I : Thunks) { + const CXXMethodDecl *MD = I.first; std::string MethodName = PredefinedExpr::ComputeName( PredefinedExpr::PrettyFunctionNoVirtual, MD); MethodNamesAndDecls.insert(std::make_pair(MethodName, MD)); } - for (std::map<std::string, const CXXMethodDecl *>::const_iterator - I = MethodNamesAndDecls.begin(), - E = MethodNamesAndDecls.end(); - I != E; ++I) { - const std::string &MethodName = I->first; - const CXXMethodDecl *MD = I->second; + for (const auto &MethodNameAndDecl : MethodNamesAndDecls) { + const std::string &MethodName = MethodNameAndDecl.first; + const CXXMethodDecl *MD = MethodNameAndDecl.second; ThunkInfoVectorTy ThunksVector = Thunks[MD]; std::stable_sort(ThunksVector.begin(), ThunksVector.end(), @@ -3291,9 +3239,8 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { static bool setsIntersect(const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &A, ArrayRef<const CXXRecordDecl *> B) { - for (ArrayRef<const CXXRecordDecl *>::iterator I = B.begin(), E = B.end(); - I != E; ++I) { - if (A.count(*I)) + for (const CXXRecordDecl *Decl : B) { + if (A.count(Decl)) return true; } return false; @@ -3636,11 +3583,10 @@ void MicrosoftVTableContext::computeVTableRelatedInformation( VFPtrLocations[RD] = VFPtrs; MethodVFTableLocationsTy NewMethodLocations; - for (VPtrInfoVector::iterator I = VFPtrs->begin(), E = VFPtrs->end(); - I != E; ++I) { - VFTableBuilder Builder(*this, RD, *I); + for (const VPtrInfo *VFPtr : *VFPtrs) { + VFTableBuilder Builder(*this, RD, VFPtr); - VFTableIdTy id(RD, (*I)->FullOffsetInMDC); + VFTableIdTy id(RD, VFPtr->FullOffsetInMDC); assert(VFTableLayouts.count(id) == 0); SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks( Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); @@ -3672,21 +3618,20 @@ void MicrosoftVTableContext::dumpMethodLocations( std::map<MethodVFTableLocation, std::string> IndicesMap; bool HasNonzeroOffset = false; - for (MethodVFTableLocationsTy::const_iterator I = NewMethods.begin(), - E = NewMethods.end(); I != E; ++I) { - const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I->first.getDecl()); + for (const auto &I : NewMethods) { + const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl()); assert(MD->isVirtual()); std::string MethodName = PredefinedExpr::ComputeName( PredefinedExpr::PrettyFunctionNoVirtual, MD); if (isa<CXXDestructorDecl>(MD)) { - IndicesMap[I->second] = MethodName + " [scalar deleting]"; + IndicesMap[I.second] = MethodName + " [scalar deleting]"; } else { - IndicesMap[I->second] = MethodName; + IndicesMap[I.second] = MethodName; } - if (!I->second.VFPtrOffset.isZero() || I->second.VBTableIndex != 0) + if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0) HasNonzeroOffset = true; } @@ -3700,12 +3645,9 @@ void MicrosoftVTableContext::dumpMethodLocations( CharUnits LastVFPtrOffset = CharUnits::fromQuantity(-1); uint64_t LastVBIndex = 0; - for (std::map<MethodVFTableLocation, std::string>::const_iterator - I = IndicesMap.begin(), - E = IndicesMap.end(); - I != E; ++I) { - CharUnits VFPtrOffset = I->first.VFPtrOffset; - uint64_t VBIndex = I->first.VBTableIndex; + for (const auto &I : IndicesMap) { + CharUnits VFPtrOffset = I.first.VFPtrOffset; + uint64_t VBIndex = I.first.VBTableIndex; if (HasNonzeroOffset && (VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) { assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset); @@ -3717,8 +3659,8 @@ void MicrosoftVTableContext::dumpMethodLocations( LastVBIndex = VBIndex; } - uint64_t VTableIndex = I->first.Index; - const std::string &MethodName = I->second; + uint64_t VTableIndex = I.first.Index; + const std::string &MethodName = I.second; Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName << '\n'; } Out << '\n'; |