diff options
Diffstat (limited to 'lib/AST')
45 files changed, 5132 insertions, 2068 deletions
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index 91f1e20d73b6..3c587331ed07 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -255,7 +255,7 @@ void APValue::swap(APValue &RHS) { memcpy(RHS.Data.buffer, TmpData, DataSize); } -void APValue::dump() const { +LLVM_DUMP_METHOD void APValue::dump() const { dump(llvm::errs()); llvm::errs() << '\n'; } diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp index cff82e9b1003..55033b238c66 100644 --- a/lib/AST/ASTConsumer.cpp +++ b/lib/AST/ASTConsumer.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTConsumer.h" -#include "llvm/Bitcode/BitstreamReader.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclGroup.h" using namespace clang; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 64386967b220..6aad4d1d570b 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -58,7 +58,7 @@ unsigned ASTContext::NumImplicitDestructors; unsigned ASTContext::NumImplicitDestructorsDeclared; enum FloatingRank { - HalfRank, FloatRank, DoubleRank, LongDoubleRank + HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank }; RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { @@ -633,9 +633,8 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( NTTP->getPosition(), nullptr, T, TInfo, - ExpandedTypes.data(), - ExpandedTypes.size(), - ExpandedTInfos.data()); + ExpandedTypes, + ExpandedTInfos); } else { Param = NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(), SourceLocation(), @@ -734,16 +733,16 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, DependentTemplateSpecializationTypes(this_()), SubstTemplateTemplateParmPacks(this_()), GlobalNestedNameSpecifier(nullptr), Int128Decl(nullptr), - UInt128Decl(nullptr), Float128StubDecl(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), - MakeIntegerSeqDecl(nullptr), SourceMgr(SM), LangOpts(LOpts), + UInt128Decl(nullptr), BuiltinVaListDecl(nullptr), + BuiltinMSVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), + ObjCClassDecl(nullptr), ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr), + CFConstantStringTagDecl(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), MakeIntegerSeqDecl(nullptr), + TypePackElementDecl(nullptr), SourceMgr(SM), LangOpts(LOpts), SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)), AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), @@ -816,7 +815,7 @@ void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { void ASTContext::setExternalSource(IntrusiveRefCntPtr<ExternalASTSource> Source) { - ExternalSource = Source; + ExternalSource = std::move(Source); } void ASTContext::PrintStats() const { @@ -928,6 +927,14 @@ ASTContext::getMakeIntegerSeqDecl() const { return MakeIntegerSeqDecl; } +BuiltinTemplateDecl * +ASTContext::getTypePackElementDecl() const { + if (!TypePackElementDecl) + TypePackElementDecl = buildBuiltinTemplateDecl(BTK__type_pack_element, + getTypePackElementName()); + return TypePackElementDecl; +} + RecordDecl *ASTContext::buildImplicitRecord(StringRef Name, RecordDecl::TagKind TK) const { SourceLocation Loc; @@ -966,14 +973,6 @@ TypedefDecl *ASTContext::getUInt128Decl() const { return UInt128Decl; } -TypeDecl *ASTContext::getFloat128StubType() const { - assert(LangOpts.CPlusPlus && "should only be called for c++"); - if (!Float128StubDecl) - Float128StubDecl = buildImplicitRecord("__float128"); - - return Float128StubDecl; -} - void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K); R = CanQualType::CreateUnsafe(QualType(Ty, 0)); @@ -1022,6 +1021,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, InitBuiltinType(DoubleTy, BuiltinType::Double); InitBuiltinType(LongDoubleTy, BuiltinType::LongDouble); + // GNU extension, __float128 for IEEE quadruple precision + InitBuiltinType(Float128Ty, BuiltinType::Float128); + // GNU extension, 128-bit integers. InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); @@ -1083,26 +1085,17 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, FloatComplexTy = getComplexType(FloatTy); DoubleComplexTy = getComplexType(DoubleTy); LongDoubleComplexTy = getComplexType(LongDoubleTy); + Float128ComplexTy = getComplexType(Float128Ty); // Builtin types for 'id', 'Class', and 'SEL'. InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId); InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass); InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel); - if (LangOpts.OpenCL) { - InitBuiltinType(OCLImage1dTy, BuiltinType::OCLImage1d); - InitBuiltinType(OCLImage1dArrayTy, BuiltinType::OCLImage1dArray); - 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); + if (LangOpts.OpenCL) { +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + InitBuiltinType(SingletonId, BuiltinType::Id); +#include "clang/Basic/OpenCLImageTypes.def" InitBuiltinType(OCLSamplerTy, BuiltinType::OCLSampler); InitBuiltinType(OCLEventTy, BuiltinType::OCLEvent); @@ -1268,34 +1261,37 @@ void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, ASTContext::overridden_cxx_method_iterator ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const { - llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos - = OverriddenMethods.find(Method->getCanonicalDecl()); + llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = + OverriddenMethods.find(Method->getCanonicalDecl()); if (Pos == OverriddenMethods.end()) return nullptr; - return Pos->second.begin(); } ASTContext::overridden_cxx_method_iterator ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const { - llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos - = OverriddenMethods.find(Method->getCanonicalDecl()); + llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = + OverriddenMethods.find(Method->getCanonicalDecl()); if (Pos == OverriddenMethods.end()) return nullptr; - return Pos->second.end(); } unsigned ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const { - llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos - = OverriddenMethods.find(Method->getCanonicalDecl()); + llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = + OverriddenMethods.find(Method->getCanonicalDecl()); if (Pos == OverriddenMethods.end()) return 0; - return Pos->second.size(); } +ASTContext::overridden_method_range +ASTContext::overridden_methods(const CXXMethodDecl *Method) const { + return overridden_method_range(overridden_methods_begin(Method), + overridden_methods_end(Method)); +} + void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method, const CXXMethodDecl *Overridden) { assert(Method->isCanonicalDecl() && Overridden->isCanonicalDecl()); @@ -1350,6 +1346,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { case BuiltinType::Float: return Target->getFloatFormat(); case BuiltinType::Double: return Target->getDoubleFormat(); case BuiltinType::LongDouble: return Target->getLongDoubleFormat(); + case BuiltinType::Float128: return Target->getFloat128Format(); } } @@ -1480,7 +1477,7 @@ static getConstantArrayInfoInChars(const ASTContext &Context, unsigned Align = EltInfo.second.getQuantity(); if (!Context.getTargetInfo().getCXXABI().isMicrosoft() || Context.getTargetInfo().getPointerWidth(0) == 64) - Width = llvm::RoundUpToAlignment(Width, Align); + Width = llvm::alignTo(Width, Align); return std::make_pair(CharUnits::fromQuantity(Width), CharUnits::fromQuantity(Align)); } @@ -1564,7 +1561,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = EltInfo.Align; if (!getTargetInfo().getCXXABI().isMicrosoft() || getTargetInfo().getPointerWidth(0) == 64) - Width = llvm::RoundUpToAlignment(Width, Align); + Width = llvm::alignTo(Width, Align); break; } case Type::ExtVector: @@ -1577,7 +1574,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { // This happens for non-power-of-2 length vectors. if (Align & (Align-1)) { Align = llvm::NextPowerOf2(Align); - Width = llvm::RoundUpToAlignment(Width, Align); + Width = llvm::alignTo(Width, Align); } // Adjust the alignment based on the target max. uint64_t TargetVectorAlign = Target->getMaxVectorAlign(); @@ -1660,6 +1657,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = Target->getLongDoubleWidth(); Align = Target->getLongDoubleAlign(); break; + case BuiltinType::Float128: + Width = Target->getFloat128Width(); + Align = Target->getFloat128Align(); + break; case BuiltinType::NullPtr: Width = Target->getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t) Align = Target->getPointerAlign(0); // == sizeof(void*) @@ -1680,18 +1681,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { 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: +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" + // Currently these types are pointers to opaque types. Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); @@ -1903,8 +1896,8 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { if (T->isMemberPointerType()) return getPreferredTypeAlign(getPointerDiffType().getTypePtr()); - if (Target->getTriple().getArch() == llvm::Triple::xcore) - return ABIAlign; // Never overalign on XCore. + if (!Target->allowsLargerPreferedTypeAlignment()) + return ABIAlign; // Double and long long should be naturally aligned if possible. if (const ComplexType *CT = T->getAs<ComplexType>()) @@ -2991,13 +2984,18 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType, return QualType(New, 0); } +/// \brief Determine whether \p T is canonical as the result type of a function. +static bool isCanonicalResultType(QualType T) { + return T.isCanonical() && + (T.getObjCLifetime() == Qualifiers::OCL_None || + T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone); +} + /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. /// QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const { - const CallingConv CallConv = Info.getCC(); - // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; @@ -3009,8 +3007,9 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, return QualType(FT, 0); QualType Canonical; - if (!ResultTy.isCanonical()) { - Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), Info); + if (!isCanonicalResultType(ResultTy)) { + Canonical = + getFunctionNoProtoType(getCanonicalFunctionResultType(ResultTy), Info); // Get the new insert position for the node we care about. FunctionNoProtoType *NewIP = @@ -3018,21 +3017,13 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - FunctionProtoType::ExtInfo newInfo = Info.withCallingConv(CallConv); FunctionNoProtoType *New = new (*this, TypeAlignment) - FunctionNoProtoType(ResultTy, Canonical, newInfo); + FunctionNoProtoType(ResultTy, Canonical, Info); Types.push_back(New); FunctionNoProtoTypes.InsertNode(New, InsertPos); return QualType(New, 0); } -/// \brief Determine whether \p T is canonical as the result type of a function. -static bool isCanonicalResultType(QualType T) { - return T.isCanonical() && - (T.getObjCLifetime() == Qualifiers::OCL_None || - T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone); -} - CanQualType ASTContext::getCanonicalFunctionResultType(QualType ResultType) const { CanQualType CanResultType = getCanonicalType(ResultType); @@ -3099,12 +3090,13 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, // them for three variable size arrays at the end: // - parameter types // - exception types - // - consumed-arguments flags + // - extended parameter information // Instead of the exception types, there could be a noexcept // expression, or information used to resolve the exception // specification. size_t Size = sizeof(FunctionProtoType) + NumArgs * sizeof(QualType); + if (EPI.ExceptionSpec.Type == EST_Dynamic) { Size += EPI.ExceptionSpec.Exceptions.size() * sizeof(QualType); } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) { @@ -3114,8 +3106,16 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) { Size += sizeof(FunctionDecl*); } - if (EPI.ConsumedParameters) - Size += NumArgs * sizeof(bool); + + // Put the ExtParameterInfos last. If all were equal, it would make + // more sense to put these before the exception specification, because + // it's much easier to skip past them compared to the elaborate switch + // required to skip the exception specification. However, all is not + // equal; ExtParameterInfos are used to model very uncommon features, + // and it's better not to burden the more common paths. + if (EPI.ExtParameterInfos) { + Size += NumArgs * sizeof(FunctionProtoType::ExtParameterInfo); + } FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; @@ -3393,23 +3393,19 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, QualType Underlying) const { assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); - - unsigned NumArgs = Args.size(); SmallVector<TemplateArgument, 4> ArgVec; - ArgVec.reserve(NumArgs); - for (unsigned i = 0; i != NumArgs; ++i) - ArgVec.push_back(Args[i].getArgument()); + ArgVec.reserve(Args.size()); + for (const TemplateArgumentLoc &Arg : Args.arguments()) + ArgVec.push_back(Arg.getArgument()); - return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs, - Underlying); + return getTemplateSpecializationType(Template, ArgVec, Underlying); } #ifndef NDEBUG -static bool hasAnyPackExpansions(const TemplateArgument *Args, - unsigned NumArgs) { - for (unsigned I = 0; I != NumArgs; ++I) - if (Args[I].isPackExpansion()) +static bool hasAnyPackExpansions(ArrayRef<TemplateArgument> Args) { + for (const TemplateArgument &Arg : Args) + if (Arg.isPackExpansion()) return true; return true; @@ -3418,8 +3414,7 @@ static bool hasAnyPackExpansions(const TemplateArgument *Args, QualType ASTContext::getTemplateSpecializationType(TemplateName Template, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef<TemplateArgument> Args, QualType Underlying) const { assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); @@ -3436,32 +3431,29 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, else { // We can get here with an alias template when the specialization contains // a pack expansion that does not match up with a parameter pack. - assert((!IsTypeAlias || hasAnyPackExpansions(Args, NumArgs)) && + assert((!IsTypeAlias || hasAnyPackExpansions(Args)) && "Caller must compute aliased type"); IsTypeAlias = false; - CanonType = getCanonicalTemplateSpecializationType(Template, Args, - NumArgs); + CanonType = getCanonicalTemplateSpecializationType(Template, Args); } // Allocate the (non-canonical) template specialization type, but don't // try to unique it: these types typically have location information that // we don't unique and don't want to lose. void *Mem = Allocate(sizeof(TemplateSpecializationType) + - sizeof(TemplateArgument) * NumArgs + + sizeof(TemplateArgument) * Args.size() + (IsTypeAlias? sizeof(QualType) : 0), TypeAlignment); TemplateSpecializationType *Spec - = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, CanonType, + = new (Mem) TemplateSpecializationType(Template, Args, CanonType, IsTypeAlias ? Underlying : QualType()); Types.push_back(Spec); return QualType(Spec, 0); } -QualType -ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, - const TemplateArgument *Args, - unsigned NumArgs) const { +QualType ASTContext::getCanonicalTemplateSpecializationType( + TemplateName Template, ArrayRef<TemplateArgument> Args) const { assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); @@ -3472,15 +3464,16 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, // Build the canonical template specialization type. TemplateName CanonTemplate = getCanonicalTemplateName(Template); SmallVector<TemplateArgument, 4> CanonArgs; + unsigned NumArgs = Args.size(); CanonArgs.reserve(NumArgs); - for (unsigned I = 0; I != NumArgs; ++I) - CanonArgs.push_back(getCanonicalTemplateArgument(Args[I])); + for (const TemplateArgument &Arg : Args) + CanonArgs.push_back(getCanonicalTemplateArgument(Arg)); // Determine whether this canonical template specialization type already // exists. llvm::FoldingSetNodeID ID; TemplateSpecializationType::Profile(ID, CanonTemplate, - CanonArgs.data(), NumArgs, *this); + CanonArgs, *this); void *InsertPos = nullptr; TemplateSpecializationType *Spec @@ -3492,7 +3485,7 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, sizeof(TemplateArgument) * NumArgs), TypeAlignment); Spec = new (Mem) TemplateSpecializationType(CanonTemplate, - CanonArgs.data(), NumArgs, + CanonArgs, QualType(), QualType()); Types.push_back(Spec); TemplateSpecializationTypes.InsertNode(Spec, InsertPos); @@ -3592,9 +3585,7 @@ ASTContext::getDependentTemplateSpecializationType( SmallVector<TemplateArgument, 16> ArgCopy; for (unsigned I = 0, E = Args.size(); I != E; ++I) ArgCopy.push_back(Args[I].getArgument()); - return getDependentTemplateSpecializationType(Keyword, NNS, Name, - ArgCopy.size(), - ArgCopy.data()); + return getDependentTemplateSpecializationType(Keyword, NNS, Name, ArgCopy); } QualType @@ -3602,14 +3593,13 @@ ASTContext::getDependentTemplateSpecializationType( ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, - unsigned NumArgs, - const TemplateArgument *Args) const { + ArrayRef<TemplateArgument> Args) const { assert((!NNS || NNS->isDependent()) && "nested-name-specifier must be dependent"); llvm::FoldingSetNodeID ID; DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS, - Name, NumArgs, Args); + Name, Args); void *InsertPos = nullptr; DependentTemplateSpecializationType *T @@ -3623,6 +3613,7 @@ ASTContext::getDependentTemplateSpecializationType( if (Keyword == ETK_None) CanonKeyword = ETK_Typename; bool AnyNonCanonArgs = false; + unsigned NumArgs = Args.size(); SmallVector<TemplateArgument, 16> CanonArgs(NumArgs); for (unsigned I = 0; I != NumArgs; ++I) { CanonArgs[I] = getCanonicalTemplateArgument(Args[I]); @@ -3633,8 +3624,8 @@ ASTContext::getDependentTemplateSpecializationType( QualType Canon; if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) { Canon = getDependentTemplateSpecializationType(CanonKeyword, CanonNNS, - Name, NumArgs, - CanonArgs.data()); + Name, + CanonArgs); // Find the insert position again. DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -3644,7 +3635,7 @@ ASTContext::getDependentTemplateSpecializationType( sizeof(TemplateArgument) * NumArgs), TypeAlignment); T = new (Mem) DependentTemplateSpecializationType(Keyword, NNS, - Name, NumArgs, Args, Canon); + Name, Args, Canon); Types.push_back(T); DependentTemplateSpecializationTypes.InsertNode(T, InsertPos); return QualType(T, 0); @@ -4012,13 +4003,35 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType, QualType UnderlyingType, UnaryTransformType::UTTKind Kind) const { - UnaryTransformType *Ty = - new (*this, TypeAlignment) UnaryTransformType (BaseType, UnderlyingType, - Kind, - UnderlyingType->isDependentType() ? - QualType() : getCanonicalType(UnderlyingType)); - Types.push_back(Ty); - return QualType(Ty, 0); + UnaryTransformType *ut = nullptr; + + if (BaseType->isDependentType()) { + // Look in the folding set for an existing type. + llvm::FoldingSetNodeID ID; + DependentUnaryTransformType::Profile(ID, getCanonicalType(BaseType), Kind); + + void *InsertPos = nullptr; + DependentUnaryTransformType *Canon + = DependentUnaryTransformTypes.FindNodeOrInsertPos(ID, InsertPos); + + if (!Canon) { + // Build a new, canonical __underlying_type(type) type. + Canon = new (*this, TypeAlignment) + DependentUnaryTransformType(*this, getCanonicalType(BaseType), + Kind); + DependentUnaryTransformTypes.InsertNode(Canon, InsertPos); + } + ut = new (*this, TypeAlignment) UnaryTransformType (BaseType, + QualType(), Kind, + QualType(Canon, 0)); + } else { + QualType CanonType = getCanonicalType(UnderlyingType); + ut = new (*this, TypeAlignment) UnaryTransformType (BaseType, + UnderlyingType, Kind, + CanonType); + } + Types.push_back(ut); + return QualType(ut, 0); } /// getAutoType - Return the uniqued reference to the 'auto' type which has been @@ -4623,6 +4636,7 @@ static FloatingRank getFloatingRank(QualType T) { case BuiltinType::Float: return FloatRank; case BuiltinType::Double: return DoubleRank; case BuiltinType::LongDouble: return LongDoubleRank; + case BuiltinType::Float128: return Float128Rank; } } @@ -4639,6 +4653,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, case FloatRank: return FloatComplexTy; case DoubleRank: return DoubleComplexTy; case LongDoubleRank: return LongDoubleComplexTy; + case Float128Rank: return Float128ComplexTy; } } @@ -4648,6 +4663,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, case FloatRank: return FloatTy; case DoubleRank: return DoubleTy; case LongDoubleRank: return LongDoubleTy; + case Float128Rank: return Float128Ty; } llvm_unreachable("getFloatingRank(): illegal value for rank"); } @@ -4868,40 +4884,63 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const { return 1; } -// getCFConstantStringType - Return the type used for constant CFStrings. -QualType ASTContext::getCFConstantStringType() const { +TypedefDecl *ASTContext::getCFConstantStringDecl() const { if (!CFConstantStringTypeDecl) { - CFConstantStringTypeDecl = buildImplicitRecord("NSConstantString"); - CFConstantStringTypeDecl->startDefinition(); + assert(!CFConstantStringTagDecl && + "tag and typedef should be initialized together"); + CFConstantStringTagDecl = buildImplicitRecord("__NSConstantString_tag"); + CFConstantStringTagDecl->startDefinition(); QualType FieldTypes[4]; + const char *FieldNames[4]; // const int *isa; FieldTypes[0] = getPointerType(IntTy.withConst()); + FieldNames[0] = "isa"; // int flags; FieldTypes[1] = IntTy; + FieldNames[1] = "flags"; // const char *str; FieldTypes[2] = getPointerType(CharTy.withConst()); + FieldNames[2] = "str"; // long length; FieldTypes[3] = LongTy; + FieldNames[3] = "length"; // Create fields for (unsigned i = 0; i < 4; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl, + FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTagDecl, + SourceLocation(), SourceLocation(), - SourceLocation(), nullptr, + &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/nullptr, /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); - CFConstantStringTypeDecl->addDecl(Field); + CFConstantStringTagDecl->addDecl(Field); } - CFConstantStringTypeDecl->completeDefinition(); + CFConstantStringTagDecl->completeDefinition(); + // This type is designed to be compatible with NSConstantString, but cannot + // use the same name, since NSConstantString is an interface. + auto tagType = getTagDeclType(CFConstantStringTagDecl); + CFConstantStringTypeDecl = + buildImplicitTypedef(tagType, "__NSConstantString"); } - return getTagDeclType(CFConstantStringTypeDecl); + return CFConstantStringTypeDecl; +} + +RecordDecl *ASTContext::getCFConstantStringTagDecl() const { + if (!CFConstantStringTagDecl) + getCFConstantStringDecl(); // Build the tag and the typedef. + return CFConstantStringTagDecl; +} + +// getCFConstantStringType - Return the type used for constant CFStrings. +QualType ASTContext::getCFConstantStringType() const { + return getTypedefType(getCFConstantStringDecl()); } QualType ASTContext::getObjCSuperType() const { @@ -4914,9 +4953,13 @@ QualType ASTContext::getObjCSuperType() const { } void ASTContext::setCFConstantStringType(QualType T) { - const RecordType *Rec = T->getAs<RecordType>(); - assert(Rec && "Invalid CFConstantStringType"); - CFConstantStringTypeDecl = Rec->getDecl(); + const TypedefType *TD = T->getAs<TypedefType>(); + assert(TD && "Invalid CFConstantStringType"); + CFConstantStringTypeDecl = cast<TypedefDecl>(TD->getDecl()); + auto TagType = + CFConstantStringTypeDecl->getUnderlyingType()->getAs<RecordType>(); + assert(TagType && "Invalid CFConstantStringType"); + CFConstantStringTagDecl = TagType->getDecl(); } QualType ASTContext::getBlockDescriptorType() const { @@ -5096,6 +5139,27 @@ bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const { !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit(); } +ASTContext::InlineVariableDefinitionKind +ASTContext::getInlineVariableDefinitionKind(const VarDecl *VD) const { + if (!VD->isInline()) + return InlineVariableDefinitionKind::None; + + // In almost all cases, it's a weak definition. + auto *First = VD->getFirstDecl(); + if (!First->isConstexpr() || First->isInlineSpecified() || + !VD->isStaticDataMember()) + return InlineVariableDefinitionKind::Weak; + + // If there's a file-context declaration in this translation unit, it's a + // non-discardable definition. + for (auto *D : VD->redecls()) + if (D->getLexicalDeclContext()->isFileContext()) + return InlineVariableDefinitionKind::Strong; + + // If we've not seen one yet, we don't know. + return InlineVariableDefinitionKind::WeakUnknown; +} + static inline std::string charUnitsToString(const CharUnits &CU) { return llvm::itostr(CU.getQuantity()); @@ -5122,7 +5186,7 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { SourceLocation Loc; CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy); CharUnits ParmOffset = PtrSize; - for (auto PI : Decl->params()) { + for (auto PI : Decl->parameters()) { QualType PType = PI->getType(); CharUnits sz = getObjCEncodingTypeSize(PType); if (sz.isZero()) @@ -5137,7 +5201,7 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { // Argument types. ParmOffset = PtrSize; - for (auto PVDecl : Decl->params()) { + for (auto PVDecl : Decl->parameters()) { QualType PType = PVDecl->getOriginalType(); if (const ArrayType *AT = dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { @@ -5165,7 +5229,7 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, getObjCEncodingForType(Decl->getReturnType(), S); CharUnits ParmOffset; // Compute size of all parameters. - for (auto PI : Decl->params()) { + for (auto PI : Decl->parameters()) { QualType PType = PI->getType(); CharUnits sz = getObjCEncodingTypeSize(PType); if (sz.isZero()) @@ -5179,7 +5243,7 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, ParmOffset = CharUnits::Zero(); // Argument types. - for (auto PVDecl : Decl->params()) { + for (auto PVDecl : Decl->parameters()) { QualType PType = PVDecl->getOriginalType(); if (const ArrayType *AT = dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { @@ -5450,6 +5514,7 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C, case BuiltinType::LongDouble: return 'D'; case BuiltinType::NullPtr: return '*'; // like char* + case BuiltinType::Float128: case BuiltinType::Half: // FIXME: potentially need @encodes for these! return ' '; @@ -5460,18 +5525,9 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C, llvm_unreachable("@encoding ObjC primitive type"); // OpenCL and placeholder types don't need @encodings. - 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: +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: @@ -5691,8 +5747,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); llvm::raw_string_ostream OS(S); TemplateSpecializationType::PrintTemplateArgumentList(OS, - TemplateArgs.data(), - TemplateArgs.size(), + TemplateArgs.asArray(), (*this).getPrintingPolicy()); } } else { @@ -5913,7 +5968,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, QualType *NotEncodedT) const { assert(RDecl && "Expected non-null RecordDecl"); assert(!RDecl->isUnion() && "Should not be called for unions"); - if (!RDecl->getDefinition()) + if (!RDecl->getDefinition() || RDecl->getDefinition()->isInvalidDecl()) return; CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(RDecl); @@ -6354,6 +6409,7 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { // }; VaListDecl->completeDefinition(); + Context->VaListTagDecl = VaListDecl; // typedef struct __va_list __builtin_va_list; QualType T = Context->getRecordType(VaListDecl); @@ -7132,6 +7188,11 @@ QualType ASTContext::areCommonBaseCompatible( if (!LDecl || !RDecl) return QualType(); + // When either LHS or RHS is a kindof type, we should return a kindof type. + // For example, for common base of kindof(ASub1) and kindof(ASub2), we return + // kindof(A). + bool anyKindOf = LHS->isKindOfType() || RHS->isKindOfType(); + // Follow the left-hand side up the class hierarchy until we either hit a // root or find the RHS. Record the ancestors in case we don't find it. llvm::SmallDenseMap<const ObjCInterfaceDecl *, const ObjCObjectType *, 4> @@ -7166,10 +7227,12 @@ QualType ASTContext::areCommonBaseCompatible( anyChanges = true; // If anything in the LHS will have changed, build a new result type. - if (anyChanges) { + // If we need to return a kindof type but LHS is not a kindof type, we + // build a new result type. + if (anyChanges || LHS->isKindOfType() != anyKindOf) { QualType Result = getObjCInterfaceType(LHS->getInterface()); Result = getObjCObjectType(Result, LHSTypeArgs, Protocols, - LHS->isKindOfType()); + anyKindOf || LHS->isKindOfType()); return getObjCObjectPointerType(Result); } @@ -7214,10 +7277,12 @@ QualType ASTContext::areCommonBaseCompatible( if (!Protocols.empty()) anyChanges = true; - if (anyChanges) { + // If we need to return a kindof type but RHS is not a kindof type, we + // build a new result type. + if (anyChanges || RHS->isKindOfType() != anyKindOf) { QualType Result = getObjCInterfaceType(RHS->getInterface()); Result = getObjCObjectType(Result, RHSTypeArgs, Protocols, - RHS->isKindOfType()); + anyKindOf || RHS->isKindOfType()); return getObjCObjectPointerType(Result); } @@ -7461,8 +7526,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lproto->getTypeQuals() != rproto->getTypeQuals()) return QualType(); - if (LangOpts.ObjCAutoRefCount && - !FunctionTypesMatchOnNSConsumedAttrs(rproto, lproto)) + if (!doFunctionTypesMatchOnExtParameterInfos(rproto, lproto)) return QualType(); // Check parameter type compatibility @@ -7587,6 +7651,15 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, Qualifiers LQuals = LHSCan.getLocalQualifiers(); Qualifiers RQuals = RHSCan.getLocalQualifiers(); if (LQuals != RQuals) { + if (getLangOpts().OpenCL) { + if (LHSCan.getUnqualifiedType() != RHSCan.getUnqualifiedType() || + LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers()) + return QualType(); + if (LQuals.isAddressSpaceSupersetOf(RQuals)) + return LHS; + if (RQuals.isAddressSpaceSupersetOf(LQuals)) + return RHS; + } // If any of these qualifiers are different, we have a type // mismatch. if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() || @@ -7850,21 +7923,26 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, llvm_unreachable("Invalid Type::Class!"); } -bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs( - const FunctionProtoType *FromFunctionType, - const FunctionProtoType *ToFunctionType) { - if (FromFunctionType->hasAnyConsumedParams() != - ToFunctionType->hasAnyConsumedParams()) +bool ASTContext::doFunctionTypesMatchOnExtParameterInfos( + const FunctionProtoType *firstFnType, + const FunctionProtoType *secondFnType) { + // Fast path: if the first type doesn't have ext parameter infos, + // we match if and only if they second type also doesn't have them. + if (!firstFnType->hasExtParameterInfos()) + return !secondFnType->hasExtParameterInfos(); + + // Otherwise, we can only match if the second type has them. + if (!secondFnType->hasExtParameterInfos()) return false; - FunctionProtoType::ExtProtoInfo FromEPI = - FromFunctionType->getExtProtoInfo(); - FunctionProtoType::ExtProtoInfo ToEPI = - ToFunctionType->getExtProtoInfo(); - if (FromEPI.ConsumedParameters && ToEPI.ConsumedParameters) - for (unsigned i = 0, n = FromFunctionType->getNumParams(); i != n; ++i) { - if (FromEPI.ConsumedParameters[i] != ToEPI.ConsumedParameters[i]) - return false; - } + + auto firstEPI = firstFnType->getExtParameterInfos(); + auto secondEPI = secondFnType->getExtParameterInfos(); + assert(firstEPI.size() == secondEPI.size()); + + for (size_t i = 0, n = firstEPI.size(); i != n; ++i) { + if (firstEPI[i] != secondEPI[i]) + return false; + } return true; } @@ -8374,22 +8452,29 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, return GVA_DiscardableODR; } -static GVALinkage adjustGVALinkageForAttributes(GVALinkage L, const Decl *D) { +static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context, + 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>() || D->hasAttr<CUDAGlobalAttr>()) { + } else if (D->hasAttr<DLLExportAttr>()) { if (L == GVA_DiscardableODR) return GVA_StrongODR; + } else if (Context.getLangOpts().CUDA && Context.getLangOpts().CUDAIsDevice && + D->hasAttr<CUDAGlobalAttr>()) { + // Device-side functions with __global__ attribute must always be + // visible externally so they can be launched from host. + if (L == GVA_DiscardableODR || L == GVA_Internal) + return GVA_StrongODR; } return L; } GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { - return adjustGVALinkageForAttributes(basicGVALinkageForFunction(*this, FD), - FD); + return adjustGVALinkageForAttributes( + *this, basicGVALinkageForFunction(*this, FD), FD); } static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, @@ -8422,15 +8507,31 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, if (Context.isMSStaticDataMemberInlineDefinition(VD)) return GVA_DiscardableODR; + // Most non-template variables have strong linkage; inline variables are + // linkonce_odr or (occasionally, for compatibility) weak_odr. + GVALinkage StrongLinkage; + switch (Context.getInlineVariableDefinitionKind(VD)) { + case ASTContext::InlineVariableDefinitionKind::None: + StrongLinkage = GVA_StrongExternal; + break; + case ASTContext::InlineVariableDefinitionKind::Weak: + case ASTContext::InlineVariableDefinitionKind::WeakUnknown: + StrongLinkage = GVA_DiscardableODR; + break; + case ASTContext::InlineVariableDefinitionKind::Strong: + StrongLinkage = GVA_StrongODR; + break; + } + switch (VD->getTemplateSpecializationKind()) { case TSK_Undeclared: - return GVA_StrongExternal; + return StrongLinkage; case TSK_ExplicitSpecialization: return Context.getTargetInfo().getCXXABI().isMicrosoft() && VD->isStaticDataMember() ? GVA_StrongODR - : GVA_StrongExternal; + : StrongLinkage; case TSK_ExplicitInstantiationDefinition: return GVA_StrongODR; @@ -8446,8 +8547,8 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, } GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { - return adjustGVALinkageForAttributes(basicGVALinkageForVariable(*this, VD), - VD); + return adjustGVALinkageForAttributes( + *this, basicGVALinkageForVariable(*this, VD), VD); } bool ASTContext::DeclMustBeEmitted(const Decl *D) { @@ -8464,8 +8565,17 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // We never need to emit an uninstantiated function template. if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) return false; - } else if (isa<OMPThreadPrivateDecl>(D)) + } else if (isa<PragmaCommentDecl>(D)) + return true; + else if (isa<OMPThreadPrivateDecl>(D) || + D->hasAttr<OMPDeclareTargetDeclAttr>()) return true; + else if (isa<PragmaDetectMismatchDecl>(D)) + return true; + else if (isa<OMPThreadPrivateDecl>(D)) + return !D->getDeclContext()->isDependentContext(); + else if (isa<OMPDeclareReductionDecl>(D)) + return !D->getDeclContext()->isDependentContext(); else return false; @@ -8545,8 +8655,25 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, if (IsCXXMethod) return ABI->getDefaultMethodCallConv(IsVariadic); - if (LangOpts.MRTD && !IsVariadic) return CC_X86StdCall; - + switch (LangOpts.getDefaultCallingConv()) { + case LangOptions::DCC_None: + break; + case LangOptions::DCC_CDecl: + return CC_C; + case LangOptions::DCC_FastCall: + if (getTargetInfo().hasFeature("sse2")) + return CC_X86FastCall; + break; + case LangOptions::DCC_StdCall: + if (!IsVariadic) + return CC_X86StdCall; + break; + case LangOptions::DCC_VectorCall: + // __vectorcall cannot be applied to variadic functions. + if (!IsVariadic) + return CC_X86VectorCall; + break; + } return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown); } @@ -8626,6 +8753,8 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth) const { return DoubleTy; case TargetInfo::LongDouble: return LongDoubleTy; + case TargetInfo::Float128: + return Float128Ty; case TargetInfo::NoFloat: return QualType(); } @@ -8639,8 +8768,7 @@ void ASTContext::setManglingNumber(const NamedDecl *ND, unsigned Number) { } unsigned ASTContext::getManglingNumber(const NamedDecl *ND) const { - llvm::DenseMap<const NamedDecl *, unsigned>::const_iterator I = - MangleNumbers.find(ND); + auto I = MangleNumbers.find(ND); return I != MangleNumbers.end() ? I->second : 1; } @@ -8650,8 +8778,7 @@ void ASTContext::setStaticLocalNumber(const VarDecl *VD, unsigned Number) { } unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const { - llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = - StaticLocalNumbers.find(VD); + auto I = StaticLocalNumbers.find(VD); return I != StaticLocalNumbers.end() ? I->second : 1; } diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 2ab5a32917ae..22de8bc0dd05 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -10,6 +10,7 @@ // This file implements a diagnostic formatting hook for AST elements. // //===----------------------------------------------------------------------===// + #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" @@ -118,7 +119,7 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { if (DesugarArgument) { ShouldAKA = true; QT = Context.getTemplateSpecializationType( - TST->getTemplateName(), Args.data(), Args.size(), QT); + TST->getTemplateName(), Args, QT); } break; } @@ -443,7 +444,6 @@ void clang::FormatASTNodeDiagnosticArgument( NeedQuotes = false; break; } - } if (NeedQuotes) { @@ -497,7 +497,7 @@ class TemplateDiff { enum DiffKind { /// Incomplete or invalid node. Invalid, - /// Another level of templates, requires that + /// Another level of templates Template, /// Type difference, all type differences except those falling under /// the Template difference. @@ -616,7 +616,7 @@ class TemplateDiff { SetDefault(FromDefault, ToDefault); } - void SetIntegerDiff(llvm::APSInt FromInt, llvm::APSInt ToInt, + void SetIntegerDiff(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt, bool IsValidFromInt, bool IsValidToInt, QualType FromIntType, QualType ToIntType, Expr *FromExpr, Expr *ToExpr, bool FromDefault, @@ -653,7 +653,7 @@ class TemplateDiff { void SetFromDeclarationAndToIntegerDiff( ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr, - Expr *FromExpr, llvm::APSInt ToInt, bool IsValidToInt, + Expr *FromExpr, const llvm::APSInt &ToInt, bool IsValidToInt, QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) { assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger; @@ -669,7 +669,7 @@ class TemplateDiff { } void SetFromIntegerAndToDeclarationDiff( - llvm::APSInt FromInt, bool IsValidFromInt, QualType FromIntType, + const llvm::APSInt &FromInt, bool IsValidFromInt, QualType FromIntType, Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf, bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) { assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); @@ -990,19 +990,22 @@ class TemplateDiff { } }; + bool UseDesugaredIterator; InternalIterator SugaredIterator; InternalIterator DesugaredIterator; public: TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) - : SugaredIterator(TST), + : UseDesugaredIterator(TST->isSugared() && !TST->isTypeAlias()), + SugaredIterator(TST), DesugaredIterator( GetTemplateSpecializationType(Context, TST->desugar())) {} /// &operator++ - Increment the iterator to the next template argument. TSTiterator &operator++() { ++SugaredIterator; - ++DesugaredIterator; + if (UseDesugaredIterator) + ++DesugaredIterator; return *this; } @@ -1024,11 +1027,13 @@ class TemplateDiff { /// hasDesugaredTA - Returns true if there is another TemplateArgument /// available. bool hasDesugaredTA() const { - return !DesugaredIterator.isEnd(); + return UseDesugaredIterator && !DesugaredIterator.isEnd(); } /// getDesugaredTA - Returns the desugared TemplateArgument. reference getDesugaredTA() const { + assert(UseDesugaredIterator && + "Desugared TemplateArgument should not be used."); return *DesugaredIterator; } }; @@ -1055,8 +1060,7 @@ class TemplateDiff { Ty = Context.getTemplateSpecializationType( TemplateName(CTSD->getSpecializedTemplate()), - CTSD->getTemplateArgs().data(), - CTSD->getTemplateArgs().size(), + CTSD->getTemplateArgs().asArray(), Ty.getLocalUnqualifiedType().getCanonicalType()); return Ty->getAs<TemplateSpecializationType>(); @@ -1523,12 +1527,14 @@ class TemplateDiff { OS << FromTD->getNameAsString() << '<'; Tree.MoveToChild(); unsigned NumElideArgs = 0; + bool AllArgsElided = true; do { if (ElideType) { if (Tree.NodeIsSame()) { ++NumElideArgs; continue; } + AllArgsElided = false; if (NumElideArgs > 0) { PrintElideArgs(NumElideArgs, Indent); NumElideArgs = 0; @@ -1539,8 +1545,12 @@ class TemplateDiff { if (Tree.HasNextSibling()) OS << ", "; } while (Tree.AdvanceSibling()); - if (NumElideArgs > 0) - PrintElideArgs(NumElideArgs, Indent); + if (NumElideArgs > 0) { + if (AllArgsElided) + OS << "..."; + else + PrintElideArgs(NumElideArgs, Indent); + } Tree.Parent(); OS << ">"; @@ -1622,7 +1632,6 @@ class TemplateDiff { Unbold(); OS << "]"; } - return; } /// PrintExpr - Prints out the expr template arguments, highlighting argument @@ -1695,7 +1704,7 @@ class TemplateDiff { /// PrintAPSInt - Handles printing of integral arguments, highlighting /// argument differences. - void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt, + void PrintAPSInt(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt, bool IsValidFromInt, bool IsValidToInt, QualType FromIntType, QualType ToIntType, Expr *FromExpr, Expr *ToExpr, bool FromDefault, bool ToDefault, bool Same) { @@ -1728,8 +1737,8 @@ class TemplateDiff { /// PrintAPSInt - If valid, print the APSInt. If the expression is /// gives more information, print it too. - void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid, QualType IntType, - bool PrintType) { + void PrintAPSInt(const llvm::APSInt &Val, Expr *E, bool Valid, + QualType IntType, bool PrintType) { Bold(); if (Valid) { if (HasExtraInfo(E)) { @@ -1834,14 +1843,13 @@ class TemplateDiff { Unbold(); OS << ']'; } - } /// PrintValueDeclAndInteger - Uses the print functions for ValueDecl and /// APSInt to print a mixed difference. void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf, bool IsNullPtr, Expr *VDExpr, bool DefaultDecl, - llvm::APSInt Val, QualType IntType, + const llvm::APSInt &Val, QualType IntType, Expr *IntExpr, bool DefaultInt) { if (!PrintTree) { OS << (DefaultDecl ? "(default) " : ""); @@ -1861,7 +1869,7 @@ class TemplateDiff { /// PrintIntegerAndValueDecl - Uses the print functions for APSInt and /// ValueDecl to print a mixed difference. - void PrintIntegerAndValueDecl(llvm::APSInt Val, QualType IntType, + void PrintIntegerAndValueDecl(const llvm::APSInt &Val, QualType IntType, Expr *IntExpr, bool DefaultInt, ValueDecl *VD, bool NeedAddressOf, bool IsNullPtr, Expr *VDExpr, bool DefaultDecl) { @@ -2016,7 +2024,7 @@ public: return true; } }; // end class TemplateDiff -} // end namespace +} // end anonymous namespace /// FormatTemplateTypeDiff - A helper static function to start the template /// diff and return the properly formatted string. Returns true if the diff diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 4622a75ac2c6..872ba356a9b2 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -18,13 +18,14 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclLookups.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclVisitor.h" +#include "clang/AST/LocInfoType.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; @@ -403,6 +404,9 @@ namespace { void VisitAtomicType(const AtomicType *T) { dumpTypeAsChild(T->getValueType()); } + void VisitPipeType(const PipeType *T) { + dumpTypeAsChild(T->getElementType()); + } void VisitAdjustedType(const AdjustedType *T) { dumpTypeAsChild(T->getOriginalType()); } @@ -426,6 +430,14 @@ namespace { void VisitVarDecl(const VarDecl *D); void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D); void VisitImportDecl(const ImportDecl *D); + void VisitPragmaCommentDecl(const PragmaCommentDecl *D); + void VisitPragmaDetectMismatchDecl(const PragmaDetectMismatchDecl *D); + void VisitCapturedDecl(const CapturedDecl *D); + + // OpenMP decls + void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D); + void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D); + void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D); // C++ Decls void VisitNamespaceDecl(const NamespaceDecl *D); @@ -462,6 +474,7 @@ namespace { void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D); void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D); void VisitUsingShadowDecl(const UsingShadowDecl *D); + void VisitConstructorUsingShadowDecl(const ConstructorUsingShadowDecl *D); void VisitLinkageSpecDecl(const LinkageSpecDecl *D); void VisitAccessSpecDecl(const AccessSpecDecl *D); void VisitFriendDecl(const FriendDecl *D); @@ -487,6 +500,10 @@ namespace { void VisitLabelStmt(const LabelStmt *Node); void VisitGotoStmt(const GotoStmt *Node); void VisitCXXCatchStmt(const CXXCatchStmt *Node); + void VisitCapturedStmt(const CapturedStmt *Node); + + // OpenMP + void VisitOMPExecutableDirective(const OMPExecutableDirective *Node); // Exprs void VisitExpr(const Expr *Node); @@ -697,6 +714,12 @@ void ASTDumper::dumpTypeAsChild(const Type *T) { } void ASTDumper::dumpBareDeclRef(const Decl *D) { + if (!D) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } + { ColorScope Color(*this, DeclKindNameColor); OS << D->getDeclKindName(); @@ -819,8 +842,6 @@ void ASTDumper::dumpAttr(const Attr *A) { switch (A->getKind()) { #define ATTR(X) case attr::X: OS << #X; break; #include "clang/Basic/AttrList.inc" - default: - llvm_unreachable("unexpected attribute kind"); } OS << "Attr"; } @@ -1140,10 +1161,8 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { if (!D->param_begin() && D->getNumParams()) dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; }); else - for (FunctionDecl::param_const_iterator I = D->param_begin(), - E = D->param_end(); - I != E; ++I) - dumpDecl(*I); + for (const ParmVarDecl *Parameter : D->parameters()) + dumpDecl(Parameter); if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D)) for (CXXConstructorDecl::init_const_iterator I = C->init_begin(), @@ -1184,6 +1203,10 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) { OS << " __module_private__"; if (D->isNRVOVariable()) OS << " nrvo"; + if (D->isInline()) + OS << " inline"; + if (D->isConstexpr()) + OS << " constexpr"; if (D->hasInit()) { switch (D->getInitStyle()) { case VarDecl::CInit: OS << " cinit"; break; @@ -1202,6 +1225,56 @@ void ASTDumper::VisitImportDecl(const ImportDecl *D) { OS << ' ' << D->getImportedModule()->getFullModuleName(); } +void ASTDumper::VisitPragmaCommentDecl(const PragmaCommentDecl *D) { + OS << ' '; + switch (D->getCommentKind()) { + case PCK_Unknown: llvm_unreachable("unexpected pragma comment kind"); + case PCK_Compiler: OS << "compiler"; break; + case PCK_ExeStr: OS << "exestr"; break; + case PCK_Lib: OS << "lib"; break; + case PCK_Linker: OS << "linker"; break; + case PCK_User: OS << "user"; break; + } + StringRef Arg = D->getArg(); + if (!Arg.empty()) + OS << " \"" << Arg << "\""; +} + +void ASTDumper::VisitPragmaDetectMismatchDecl( + const PragmaDetectMismatchDecl *D) { + OS << " \"" << D->getName() << "\" \"" << D->getValue() << "\""; +} + +void ASTDumper::VisitCapturedDecl(const CapturedDecl *D) { + dumpStmt(D->getBody()); +} + +//===----------------------------------------------------------------------===// +// OpenMP Declarations +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { + for (auto *E : D->varlists()) + dumpStmt(E); +} + +void ASTDumper::VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { + dumpName(D); + dumpType(D->getType()); + OS << " combiner"; + dumpStmt(D->getCombiner()); + if (auto *Initializer = D->getInitializer()) { + OS << " initializer"; + dumpStmt(Initializer); + } +} + +void ASTDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { + dumpName(D); + dumpType(D->getType()); + dumpStmt(D->getInit()); +} + //===----------------------------------------------------------------------===// // C++ Declarations //===----------------------------------------------------------------------===// @@ -1425,6 +1498,31 @@ void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { dumpTypeAsChild(TD->getTypeForDecl()); } +void ASTDumper::VisitConstructorUsingShadowDecl( + const ConstructorUsingShadowDecl *D) { + if (D->constructsVirtualBase()) + OS << " virtual"; + + dumpChild([=] { + OS << "target "; + dumpBareDeclRef(D->getTargetDecl()); + }); + + dumpChild([=] { + OS << "nominated "; + dumpBareDeclRef(D->getNominatedBaseClass()); + OS << ' '; + dumpBareDeclRef(D->getNominatedBaseClassShadowDecl()); + }); + + dumpChild([=] { + OS << "constructed "; + dumpBareDeclRef(D->getConstructedBaseClass()); + OS << ' '; + dumpBareDeclRef(D->getConstructedBaseClassShadowDecl()); + }); +} + void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { switch (D->getLanguage()) { case LinkageSpecDecl::lang_c: OS << " C"; break; @@ -1484,10 +1582,8 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { if (D->isThisDeclarationADefinition()) { dumpDeclContext(D); } else { - for (ObjCMethodDecl::param_const_iterator I = D->param_begin(), - E = D->param_end(); - I != E; ++I) - dumpDecl(*I); + for (const ParmVarDecl *Parameter : D->parameters()) + dumpDecl(Parameter); } if (D->isVariadic()) @@ -1597,6 +1693,8 @@ void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { OS << " strong"; if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) OS << " unsafe_unretained"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_class) + OS << " class"; if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) dumpDeclRef(D->getGetterMethodDecl(), "getter"); if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) @@ -1615,7 +1713,7 @@ void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { } void ASTDumper::VisitBlockDecl(const BlockDecl *D) { - for (auto I : D->params()) + for (auto I : D->parameters()) dumpDecl(I); if (D->isVariadic()) @@ -1707,6 +1805,41 @@ void ASTDumper::VisitCXXCatchStmt(const CXXCatchStmt *Node) { dumpDecl(Node->getExceptionDecl()); } +void ASTDumper::VisitCapturedStmt(const CapturedStmt *Node) { + VisitStmt(Node); + dumpDecl(Node->getCapturedDecl()); +} + +//===----------------------------------------------------------------------===// +// OpenMP dumping methods. +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitOMPExecutableDirective( + const OMPExecutableDirective *Node) { + VisitStmt(Node); + for (auto *C : Node->clauses()) { + dumpChild([=] { + if (!C) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>> OMPClause"; + return; + } + { + ColorScope Color(*this, AttrColor); + StringRef ClauseName(getOpenMPClauseName(C->getClauseKind())); + OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper() + << ClauseName.drop_front() << "Clause"; + } + dumpPointer(C); + dumpSourceRange(SourceRange(C->getLocStart(), C->getLocEnd())); + if (C->isImplicit()) + OS << " <implicit>"; + for (auto *S : C->children()) + dumpStmt(S); + }); + } +} + //===----------------------------------------------------------------------===// // Expr dumping methods. //===----------------------------------------------------------------------===// @@ -2076,8 +2209,10 @@ void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { void ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) { VisitExpr(Node); - OS << " selector="; - Node->getBoxingMethod()->getSelector().print(OS); + if (auto *BoxingMethod = Node->getBoxingMethod()) { + OS << " selector="; + BoxingMethod->getSelector().print(OS); + } } void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 916f1081798d..bc1f9f96a06b 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -29,7 +29,7 @@ namespace clang { public DeclVisitor<ASTNodeImporter, Decl *>, public StmtVisitor<ASTNodeImporter, Stmt *> { ASTImporter &Importer; - + public: explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) { } @@ -64,11 +64,12 @@ namespace clang { QualType VisitDecltypeType(const DecltypeType *T); QualType VisitUnaryTransformType(const UnaryTransformType *T); QualType VisitAutoType(const AutoType *T); + QualType VisitInjectedClassNameType(const InjectedClassNameType *T); // FIXME: DependentDecltypeType QualType VisitRecordType(const RecordType *T); QualType VisitEnumType(const EnumType *T); QualType VisitAttributedType(const AttributedType *T); - // FIXME: TemplateTypeParmType + QualType VisitTemplateTypeParmType(const TemplateTypeParmType *T); // FIXME: SubstTemplateTypeParmType QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T); QualType VisitElaboratedType(const ElaboratedType *T); @@ -86,6 +87,10 @@ namespace clang { void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); + + typedef DesignatedInitExpr::Designator Designator; + Designator ImportDesignator(const Designator &D); + /// \brief What we should import from the definition. enum ImportDefinitionKind { @@ -130,11 +135,13 @@ namespace clang { bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); Decl *VisitDecl(Decl *D); + Decl *VisitAccessSpecDecl(AccessSpecDecl *D); Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); Decl *VisitTypedefDecl(TypedefDecl *D); Decl *VisitTypeAliasDecl(TypeAliasDecl *D); + Decl *VisitLabelDecl(LabelDecl *D); Decl *VisitEnumDecl(EnumDecl *D); Decl *VisitRecordDecl(RecordDecl *D); Decl *VisitEnumConstantDecl(EnumConstantDecl *D); @@ -174,6 +181,7 @@ namespace clang { DeclGroupRef ImportDeclGroup(DeclGroupRef DG); Stmt *VisitStmt(Stmt *S); + Stmt *VisitGCCAsmStmt(GCCAsmStmt *S); Stmt *VisitDeclStmt(DeclStmt *S); Stmt *VisitNullStmt(NullStmt *S); Stmt *VisitCompoundStmt(CompoundStmt *S); @@ -191,7 +199,6 @@ namespace clang { Stmt *VisitContinueStmt(ContinueStmt *S); Stmt *VisitBreakStmt(BreakStmt *S); Stmt *VisitReturnStmt(ReturnStmt *S); - // FIXME: GCCAsmStmt // FIXME: MSAsmStmt // FIXME: SEHExceptStmt // FIXME: SEHFinallyStmt @@ -212,21 +219,69 @@ namespace clang { // Importing expressions Expr *VisitExpr(Expr *E); + Expr *VisitVAArgExpr(VAArgExpr *E); + Expr *VisitGNUNullExpr(GNUNullExpr *E); + Expr *VisitPredefinedExpr(PredefinedExpr *E); Expr *VisitDeclRefExpr(DeclRefExpr *E); + Expr *VisitImplicitValueInitExpr(ImplicitValueInitExpr *ILE); + Expr *VisitDesignatedInitExpr(DesignatedInitExpr *E); + Expr *VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); Expr *VisitIntegerLiteral(IntegerLiteral *E); + Expr *VisitFloatingLiteral(FloatingLiteral *E); Expr *VisitCharacterLiteral(CharacterLiteral *E); + Expr *VisitStringLiteral(StringLiteral *E); + Expr *VisitCompoundLiteralExpr(CompoundLiteralExpr *E); + Expr *VisitAtomicExpr(AtomicExpr *E); + Expr *VisitAddrLabelExpr(AddrLabelExpr *E); Expr *VisitParenExpr(ParenExpr *E); + Expr *VisitParenListExpr(ParenListExpr *E); + Expr *VisitStmtExpr(StmtExpr *E); Expr *VisitUnaryOperator(UnaryOperator *E); Expr *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); Expr *VisitBinaryOperator(BinaryOperator *E); + Expr *VisitConditionalOperator(ConditionalOperator *E); + Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E); + Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E); Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E); Expr *VisitImplicitCastExpr(ImplicitCastExpr *E); Expr *VisitCStyleCastExpr(CStyleCastExpr *E); Expr *VisitCXXConstructExpr(CXXConstructExpr *E); + Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E); + Expr *VisitCXXThisExpr(CXXThisExpr *E); + Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); Expr *VisitMemberExpr(MemberExpr *E); Expr *VisitCallExpr(CallExpr *E); + Expr *VisitInitListExpr(InitListExpr *E); + Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); + Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E); + + template<typename IIter, typename OIter> + void ImportArray(IIter Ibegin, IIter Iend, OIter Obegin) { + typedef typename std::remove_reference<decltype(*Obegin)>::type ItemT; + ASTImporter &ImporterRef = Importer; + std::transform(Ibegin, Iend, Obegin, + [&ImporterRef](ItemT From) -> ItemT { + return ImporterRef.Import(From); + }); + } + + template<typename IIter, typename OIter> + bool ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { + typedef typename std::remove_reference<decltype(**Obegin)>::type ItemT; + ASTImporter &ImporterRef = Importer; + bool Failed = false; + std::transform(Ibegin, Iend, Obegin, + [&ImporterRef, &Failed](ItemT *From) -> ItemT * { + ItemT *To = ImporterRef.Import(From); + if (!To && From) + Failed = true; + return To; + }); + return Failed; + } }; } + using namespace clang; //---------------------------------------------------------------------------- @@ -618,8 +673,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, Function1->getReturnType(), Function2->getReturnType())) return false; - if (Function1->getExtInfo() != Function2->getExtInfo()) - return false; + if (Function1->getExtInfo() != Function2->getExtInfo()) + return false; break; } @@ -974,7 +1029,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, /// including the next assigned index (if none of them match). Returns an /// empty option if the context is not a record, i.e.. if the anonymous /// struct/union is at namespace or block scope. -static Optional<unsigned> findAnonymousStructOrUnionIndex(RecordDecl *Anon) { +static Optional<unsigned> findUntaggedStructOrUnionIndex(RecordDecl *Anon) { ASTContext &Context = Anon->getASTContext(); QualType AnonTy = Context.getRecordType(Anon); @@ -985,13 +1040,29 @@ static Optional<unsigned> findAnonymousStructOrUnionIndex(RecordDecl *Anon) { unsigned Index = 0; for (const auto *D : Owner->noload_decls()) { const auto *F = dyn_cast<FieldDecl>(D); - if (!F || !F->isAnonymousStructOrUnion()) + if (!F) continue; - if (Context.hasSameType(F->getType(), AnonTy)) - break; + if (F->isAnonymousStructOrUnion()) { + if (Context.hasSameType(F->getType(), AnonTy)) + break; + ++Index; + continue; + } - ++Index; + // If the field looks like this: + // struct { ... } A; + QualType FieldType = F->getType(); + if (const auto *RecType = dyn_cast<RecordType>(FieldType)) { + const RecordDecl *RecDecl = RecType->getDecl(); + if (RecDecl->getDeclContext() == Owner && + !RecDecl->getIdentifier()) { + if (Context.hasSameType(FieldType, AnonTy)) + break; + ++Index; + continue; + } + } } return Index; @@ -1013,8 +1084,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (D1->isAnonymousStructOrUnion() && D2->isAnonymousStructOrUnion()) { // If both anonymous structs/unions are in a record context, make sure // they occur in the same location in the context records. - if (Optional<unsigned> Index1 = findAnonymousStructOrUnionIndex(D1)) { - if (Optional<unsigned> Index2 = findAnonymousStructOrUnionIndex(D2)) { + if (Optional<unsigned> Index1 = findUntaggedStructOrUnionIndex(D1)) { + if (Optional<unsigned> Index2 = findUntaggedStructOrUnionIndex(D2)) { if (*Index1 != *Index2) return false; } @@ -1480,6 +1551,10 @@ QualType ASTNodeImporter::VisitType(const Type *T) { QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { switch (T->getKind()) { +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: \ + return Importer.getToContext().SingletonId; +#include "clang/Basic/OpenCLImageTypes.def" #define SHARED_SINGLETON_TYPE(Expansion) #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: return Importer.getToContext().SingletonId; @@ -1758,6 +1833,28 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) { /*IsDependent*/false); } +QualType ASTNodeImporter::VisitInjectedClassNameType( + const InjectedClassNameType *T) { + CXXRecordDecl *D = cast_or_null<CXXRecordDecl>(Importer.Import(T->getDecl())); + if (!D) + return QualType(); + + QualType InjType = Importer.Import(T->getInjectedSpecializationType()); + if (InjType.isNull()) + return QualType(); + + // FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading + // See comments in InjectedClassNameType definition for details + // return Importer.getToContext().getInjectedClassNameType(D, InjType); + enum { + TypeAlignmentInBits = 4, + TypeAlignment = 1 << TypeAlignmentInBits + }; + + return QualType(new (Importer.getToContext(), TypeAlignment) + InjectedClassNameType(D, InjType), 0); +} + QualType ASTNodeImporter::VisitRecordType(const RecordType *T) { RecordDecl *ToDecl = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl())); @@ -1797,6 +1894,18 @@ QualType ASTNodeImporter::VisitAttributedType(const AttributedType *T) { ToModifiedType, ToEquivalentType); } + +QualType ASTNodeImporter::VisitTemplateTypeParmType( + const TemplateTypeParmType *T) { + TemplateTypeParmDecl *ParmDecl = + cast_or_null<TemplateTypeParmDecl>(Importer.Import(T->getDecl())); + if (!ParmDecl && T->getDecl()) + return QualType(); + + return Importer.getToContext().getTemplateTypeParmType( + T->getDepth(), T->getIndex(), T->isParameterPack(), ParmDecl); +} + QualType ASTNodeImporter::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { TemplateName ToTemplate = Importer.Import(T->getTemplateName()); @@ -1816,8 +1925,7 @@ QualType ASTNodeImporter::VisitTemplateSpecializationType( return QualType(); } return Importer.getToContext().getTemplateSpecializationType(ToTemplate, - ToTemplateArgs.data(), - ToTemplateArgs.size(), + ToTemplateArgs, ToCanonType); } @@ -2023,6 +2131,9 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.HasInClassInitializer = FromData.HasInClassInitializer; ToData.HasUninitializedReferenceMember = FromData.HasUninitializedReferenceMember; + ToData.HasUninitializedFields = FromData.HasUninitializedFields; + ToData.HasInheritedConstructor = FromData.HasInheritedConstructor; + ToData.HasInheritedAssignment = FromData.HasInheritedAssignment; ToData.NeedOverloadResolutionForMoveConstructor = FromData.NeedOverloadResolutionForMoveConstructor; ToData.NeedOverloadResolutionForMoveAssignment @@ -2038,6 +2149,8 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor; ToData.HasConstexprNonCopyMoveConstructor = FromData.HasConstexprNonCopyMoveConstructor; + ToData.HasDefaultedDefaultConstructor + = FromData.HasDefaultedDefaultConstructor; ToData.DefaultedDefaultConstructorIsConstexpr = FromData.DefaultedDefaultConstructorIsConstexpr; ToData.HasConstexprDefaultConstructor @@ -2316,6 +2429,31 @@ Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { return ToD; } +Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { + + SourceLocation Loc = Importer.Import(D->getLocation()); + SourceLocation ColonLoc = Importer.Import(D->getColonLoc()); + + // Import the context of this declaration. + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + if (!DC) + return nullptr; + + AccessSpecDecl *accessSpecDecl + = AccessSpecDecl::Create(Importer.getToContext(), D->getAccess(), + DC, Loc, ColonLoc); + + if (!accessSpecDecl) + return nullptr; + + // Lexical DeclContext and Semantic DeclContext + // is always the same for the accessSpec. + accessSpecDecl->setLexicalDeclContext(DC); + DC->addDeclInternal(accessSpecDecl); + + return accessSpecDecl; +} + Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Import the major distinguishing characteristics of this namespace. DeclContext *DC, *LexicalDC; @@ -2464,6 +2602,39 @@ Decl *ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) { return VisitTypedefNameDecl(D, /*IsAlias=*/true); } +Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) { + // Import the major distinguishing characteristics of this label. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + assert(LexicalDC->isFunctionOrMethod()); + + LabelDecl *ToLabel = D->isGnuLocal() + ? LabelDecl::Create(Importer.getToContext(), + DC, Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo(), + Importer.Import(D->getLocStart())) + : LabelDecl::Create(Importer.getToContext(), + DC, Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo()); + Importer.Imported(D, ToLabel); + + LabelStmt *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt())); + if (!Label) + return nullptr; + + ToLabel->setStmt(Label); + ToLabel->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToLabel); + return ToLabel; +} + Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Import the major distinguishing characteristics of this enum. DeclContext *DC, *LexicalDC; @@ -2594,9 +2765,9 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // If both anonymous structs/unions are in a record context, make sure // they occur in the same location in the context records. if (Optional<unsigned> Index1 - = findAnonymousStructOrUnionIndex(D)) { + = findUntaggedStructOrUnionIndex(D)) { if (Optional<unsigned> Index2 = - findAnonymousStructOrUnionIndex(FoundRecord)) { + findUntaggedStructOrUnionIndex(FoundRecord)) { if (*Index1 != *Index2) continue; } @@ -2654,11 +2825,35 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { RecordDecl *D2 = AdoptDecl; SourceLocation StartLoc = Importer.Import(D->getLocStart()); if (!D2) { - if (isa<CXXRecordDecl>(D)) { - CXXRecordDecl *D2CXX = CXXRecordDecl::Create(Importer.getToContext(), - D->getTagKind(), - DC, StartLoc, Loc, - Name.getAsIdentifierInfo()); + CXXRecordDecl *D2CXX = nullptr; + if (CXXRecordDecl *DCXX = llvm::dyn_cast<CXXRecordDecl>(D)) { + if (DCXX->isLambda()) { + TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo()); + D2CXX = CXXRecordDecl::CreateLambda(Importer.getToContext(), + DC, TInfo, Loc, + DCXX->isDependentLambda(), + DCXX->isGenericLambda(), + DCXX->getLambdaCaptureDefault()); + Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl()); + if (DCXX->getLambdaContextDecl() && !CDecl) + return nullptr; + D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), CDecl); + } else if (DCXX->isInjectedClassName()) { + // We have to be careful to do a similar dance to the one in + // Sema::ActOnStartCXXMemberDeclarations + CXXRecordDecl *const PrevDecl = nullptr; + const bool DelayTypeCreation = true; + D2CXX = CXXRecordDecl::Create( + Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation); + Importer.getToContext().getTypeDeclType( + D2CXX, llvm::dyn_cast<CXXRecordDecl>(DC)); + } else { + D2CXX = CXXRecordDecl::Create(Importer.getToContext(), + D->getTagKind(), + DC, StartLoc, Loc, + Name.getAsIdentifierInfo()); + } D2 = D2CXX; D2->setAccess(D->getAccess()); } else { @@ -2830,7 +3025,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Import the function parameters. SmallVector<ParmVarDecl *, 8> Parameters; - for (auto P : D->params()) { + for (auto P : D->parameters()) { ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P)); if (!ToP) return nullptr; @@ -2851,6 +3046,22 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()); + if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) { + SmallVector<CXXCtorInitializer *, 4> CtorInitializers; + for (CXXCtorInitializer *I : FromConstructor->inits()) { + CXXCtorInitializer *ToI = + cast_or_null<CXXCtorInitializer>(Importer.Import(I)); + if (!ToI && I) + return nullptr; + CtorInitializers.push_back(ToI); + } + CXXCtorInitializer **Memory = + new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers]; + std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory); + CXXConstructorDecl *ToCtor = llvm::cast<CXXConstructorDecl>(ToFunction); + ToCtor->setCtorInitializers(Memory); + ToCtor->setNumCtorInitializers(NumInitializers); + } } else if (isa<CXXDestructorDecl>(D)) { ToFunction = CXXDestructorDecl::Create(Importer.getToContext(), cast<CXXRecordDecl>(DC), @@ -3009,8 +3220,13 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { D->getInClassInitStyle()); ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); - if (ToField->hasInClassInitializer()) - ToField->setInClassInitializer(D->getInClassInitializer()); + if (Expr *FromInitializer = D->getInClassInitializer()) { + Expr *ToInitializer = Importer.Import(FromInitializer); + if (ToInitializer) + ToField->setInClassInitializer(ToInitializer); + else + return nullptr; + } ToField->setImplicit(D->isImplicit()); Importer.Imported(D, ToField); LexicalDC->addDeclInternal(ToField); @@ -3075,7 +3291,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create( Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, - NamedChain, D->getChainingSize()); + {NamedChain, D->getChainingSize()}); for (const auto *Attr : D->attrs()) ToIndirectField->addAttr(Attr->clone(Importer.getToContext())); @@ -3418,7 +3634,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // Import the parameters SmallVector<ParmVarDecl *, 5> ToParams; - for (auto *FromP : D->params()) { + for (auto *FromP : D->parameters()) { ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP)); if (!ToP) return nullptr; @@ -4061,7 +4277,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { } ObjCPropertyImplDecl *ToImpl - = InImpl->FindPropertyImplDecl(Property->getIdentifier()); + = InImpl->FindPropertyImplDecl(Property->getIdentifier(), + Property->getQueryKind()); if (!ToImpl) { ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getLocStart()), @@ -4246,16 +4463,16 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { CXXRecordDecl *DTemplated = D->getTemplatedDecl(); // Create the declaration that is being templated. - SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart()); - SourceLocation IdLoc = Importer.Import(DTemplated->getLocation()); - CXXRecordDecl *D2Templated = CXXRecordDecl::Create(Importer.getToContext(), - DTemplated->getTagKind(), - DC, StartLoc, IdLoc, - Name.getAsIdentifierInfo()); - D2Templated->setAccess(DTemplated->getAccess()); - D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc())); - D2Templated->setLexicalDeclContext(LexicalDC); - + // Create the declaration that is being templated. + CXXRecordDecl *D2Templated = cast_or_null<CXXRecordDecl>( + Importer.Import(DTemplated)); + if (!D2Templated) + return nullptr; + + // Resolve possible cyclic import. + if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D)) + return AlreadyImported; + // Create the class template declaration itself. TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); @@ -4351,8 +4568,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( D->getTagKind(), DC, StartLoc, IdLoc, ClassTemplate, - TemplateArgs.data(), - TemplateArgs.size(), + TemplateArgs, /*PrevDecl=*/nullptr); D2->setSpecializationKind(D->getSpecializationKind()); @@ -4553,7 +4769,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( // Create a new specialization. D2 = VarTemplateSpecializationDecl::Create( Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo, - D->getStorageClass(), TemplateArgs.data(), TemplateArgs.size()); + D->getStorageClass(), TemplateArgs); D2->setSpecializationKind(D->getSpecializationKind()); D2->setTemplateArgsInfo(D->getTemplateArgsInfo()); @@ -4599,7 +4815,78 @@ DeclGroupRef ASTNodeImporter::ImportDeclGroup(DeclGroupRef DG) { << S->getStmtClassName(); return nullptr; } - + + +Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { + SmallVector<IdentifierInfo *, 4> Names; + for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { + IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I)); + if (!ToII) + return nullptr; + Names.push_back(ToII); + } + for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { + IdentifierInfo *ToII = Importer.Import(S->getInputIdentifier(I)); + if (!ToII) + return nullptr; + Names.push_back(ToII); + } + + SmallVector<StringLiteral *, 4> Clobbers; + for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) { + StringLiteral *Clobber = cast_or_null<StringLiteral>( + Importer.Import(S->getClobberStringLiteral(I))); + if (!Clobber) + return nullptr; + Clobbers.push_back(Clobber); + } + + SmallVector<StringLiteral *, 4> Constraints; + for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { + StringLiteral *Output = cast_or_null<StringLiteral>( + Importer.Import(S->getOutputConstraintLiteral(I))); + if (!Output) + return nullptr; + Constraints.push_back(Output); + } + + for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { + StringLiteral *Input = cast_or_null<StringLiteral>( + Importer.Import(S->getInputConstraintLiteral(I))); + if (!Input) + return nullptr; + Constraints.push_back(Input); + } + + SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs()); + if (ImportArrayChecked(S->begin_outputs(), S->end_outputs(), Exprs.begin())) + return nullptr; + + if (ImportArrayChecked(S->begin_inputs(), S->end_inputs(), + Exprs.begin() + S->getNumOutputs())) + return nullptr; + + StringLiteral *AsmStr = cast_or_null<StringLiteral>( + Importer.Import(S->getAsmString())); + if (!AsmStr) + return nullptr; + + return new (Importer.getToContext()) GCCAsmStmt( + Importer.getToContext(), + Importer.Import(S->getAsmLoc()), + S->isSimple(), + S->isVolatile(), + S->getNumOutputs(), + S->getNumInputs(), + Names.data(), + Constraints.data(), + Exprs.data(), + AsmStr, + S->getNumClobbers(), + Clobbers.data(), + Importer.Import(S->getRParenLoc())); +} + Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) { DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup()); for (Decl *ToD : ToDG) { @@ -4618,16 +4905,11 @@ Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) { } Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { - SmallVector<Stmt *, 4> ToStmts(S->size()); - auto &_Importer = this->Importer; - std::transform(S->body_begin(), S->body_end(), ToStmts.begin(), - [&_Importer](Stmt *CS) -> Stmt * { - return _Importer.Import(CS); - }); - for (Stmt *ToS : ToStmts) { - if (!ToS) - return nullptr; - } + llvm::SmallVector<Stmt *, 8> ToStmts(S->size()); + + if (ImportArrayChecked(S->body_begin(), S->body_end(), ToStmts.begin())) + return nullptr; + SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc()); SourceLocation ToRBraceLoc = Importer.Import(S->getRBracLoc()); return new (Importer.getToContext()) CompoundStmt(Importer.getToContext(), @@ -4695,6 +4977,9 @@ Stmt *ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) { Stmt *ASTNodeImporter::VisitIfStmt(IfStmt *S) { SourceLocation ToIfLoc = Importer.Import(S->getIfLoc()); + Stmt *ToInit = Importer.Import(S->getInit()); + if (!ToInit && S->getInit()) + return nullptr; VarDecl *ToConditionVariable = nullptr; if (VarDecl *FromConditionVariable = S->getConditionVariable()) { ToConditionVariable = @@ -4713,12 +4998,17 @@ Stmt *ASTNodeImporter::VisitIfStmt(IfStmt *S) { if (!ToElseStmt && S->getElse()) return nullptr; return new (Importer.getToContext()) IfStmt(Importer.getToContext(), - ToIfLoc, ToConditionVariable, + ToIfLoc, S->isConstexpr(), + ToInit, + ToConditionVariable, ToCondition, ToThenStmt, ToElseLoc, ToElseStmt); } Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { + Stmt *ToInit = Importer.Import(S->getInit()); + if (!ToInit && S->getInit()) + return nullptr; VarDecl *ToConditionVariable = nullptr; if (VarDecl *FromConditionVariable = S->getConditionVariable()) { ToConditionVariable = @@ -4730,8 +5020,8 @@ Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { if (!ToCondition && S->getCond()) return nullptr; SwitchStmt *ToStmt = new (Importer.getToContext()) SwitchStmt( - Importer.getToContext(), ToConditionVariable, - ToCondition); + Importer.getToContext(), ToInit, + ToConditionVariable, ToCondition); Stmt *ToBody = Importer.Import(S->getBody()); if (!ToBody && S->getBody()) return nullptr; @@ -4905,9 +5195,13 @@ Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { dyn_cast_or_null<DeclStmt>(Importer.Import(S->getRangeStmt())); if (!ToRange && S->getRangeStmt()) return nullptr; - DeclStmt *ToBeginEnd = - dyn_cast_or_null<DeclStmt>(Importer.Import(S->getBeginEndStmt())); - if (!ToBeginEnd && S->getBeginEndStmt()) + DeclStmt *ToBegin = + dyn_cast_or_null<DeclStmt>(Importer.Import(S->getBeginStmt())); + if (!ToBegin && S->getBeginStmt()) + return nullptr; + DeclStmt *ToEnd = + dyn_cast_or_null<DeclStmt>(Importer.Import(S->getEndStmt())); + if (!ToEnd && S->getEndStmt()) return nullptr; Expr *ToCond = Importer.Import(S->getCond()); if (!ToCond && S->getCond()) @@ -4926,7 +5220,7 @@ Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { 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, + return new (Importer.getToContext()) CXXForRangeStmt(ToRange, ToBegin, ToEnd, ToCond, ToInc, ToLoopVar, ToBody, ToForLoc, ToCoawaitLoc, @@ -5042,6 +5336,48 @@ Expr *ASTNodeImporter::VisitExpr(Expr *E) { return nullptr; } +Expr *ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *SubExpr = Importer.Import(E->getSubExpr()); + if (!SubExpr && E->getSubExpr()) + return nullptr; + + TypeSourceInfo *TInfo = Importer.Import(E->getWrittenTypeInfo()); + if (!TInfo) + return nullptr; + + return new (Importer.getToContext()) VAArgExpr( + Importer.Import(E->getBuiltinLoc()), SubExpr, TInfo, + Importer.Import(E->getRParenLoc()), T, E->isMicrosoftABI()); +} + + +Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + return new (Importer.getToContext()) GNUNullExpr( + T, Importer.Import(E->getExprLoc())); +} + +Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + StringLiteral *SL = cast_or_null<StringLiteral>( + Importer.Import(E->getFunctionName())); + if (!SL && E->getFunctionName()) + return nullptr; + + return new (Importer.getToContext()) PredefinedExpr( + Importer.Import(E->getExprLoc()), T, E->getIdentType(), SL); +} + Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl())); if (!ToD) @@ -5072,6 +5408,74 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { return DRE; } +Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return NULL; + + return new (Importer.getToContext()) ImplicitValueInitExpr(T); +} + +ASTNodeImporter::Designator +ASTNodeImporter::ImportDesignator(const Designator &D) { + if (D.isFieldDesignator()) { + IdentifierInfo *ToFieldName = Importer.Import(D.getFieldName()); + // Caller checks for import error + return Designator(ToFieldName, Importer.Import(D.getDotLoc()), + Importer.Import(D.getFieldLoc())); + } + if (D.isArrayDesignator()) + return Designator(D.getFirstExprIndex(), + Importer.Import(D.getLBracketLoc()), + Importer.Import(D.getRBracketLoc())); + + assert(D.isArrayRangeDesignator()); + return Designator(D.getFirstExprIndex(), + Importer.Import(D.getLBracketLoc()), + Importer.Import(D.getEllipsisLoc()), + Importer.Import(D.getRBracketLoc())); +} + + +Expr *ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *DIE) { + Expr *Init = cast_or_null<Expr>(Importer.Import(DIE->getInit())); + if (!Init) + return nullptr; + + SmallVector<Expr *, 4> IndexExprs(DIE->getNumSubExprs() - 1); + // List elements from the second, the first is Init itself + for (unsigned I = 1, E = DIE->getNumSubExprs(); I < E; I++) { + if (Expr *Arg = cast_or_null<Expr>(Importer.Import(DIE->getSubExpr(I)))) + IndexExprs[I - 1] = Arg; + else + return nullptr; + } + + SmallVector<Designator, 4> Designators(DIE->size()); + llvm::transform(DIE->designators(), Designators.begin(), + [this](const Designator &D) -> Designator { + return ImportDesignator(D); + }); + + for (const Designator &D : DIE->designators()) + if (D.isFieldDesignator() && !D.getFieldName()) + return nullptr; + + return DesignatedInitExpr::Create( + Importer.getToContext(), Designators, + IndexExprs, Importer.Import(DIE->getEqualOrColonLoc()), + DIE->usesGNUSyntax(), Init); +} + +Expr *ASTNodeImporter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + return new (Importer.getToContext()) + CXXNullPtrLiteralExpr(T, Importer.Import(E->getLocation())); +} + Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5082,6 +5486,16 @@ Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { Importer.Import(E->getLocation())); } +Expr *ASTNodeImporter::VisitFloatingLiteral(FloatingLiteral *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + return FloatingLiteral::Create(Importer.getToContext(), + E->getValue(), E->isExact(), T, + Importer.Import(E->getLocation())); +} + Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5092,6 +5506,67 @@ Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { Importer.Import(E->getLocation())); } +Expr *ASTNodeImporter::VisitStringLiteral(StringLiteral *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<SourceLocation, 4> Locations(E->getNumConcatenated()); + ImportArray(E->tokloc_begin(), E->tokloc_end(), Locations.begin()); + + return StringLiteral::Create(Importer.getToContext(), E->getBytes(), + E->getKind(), E->isPascal(), T, + Locations.data(), Locations.size()); +} + +Expr *ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + TypeSourceInfo *TInfo = Importer.Import(E->getTypeSourceInfo()); + if (!TInfo) + return nullptr; + + Expr *Init = Importer.Import(E->getInitializer()); + if (!Init) + return nullptr; + + return new (Importer.getToContext()) CompoundLiteralExpr( + Importer.Import(E->getLParenLoc()), TInfo, T, E->getValueKind(), + Init, E->isFileScope()); +} + +Expr *ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + SmallVector<Expr *, 6> Exprs(E->getNumSubExprs()); + if (ImportArrayChecked( + E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(), + Exprs.begin())) + return nullptr; + + return new (Importer.getToContext()) AtomicExpr( + Importer.Import(E->getBuiltinLoc()), Exprs, T, E->getOp(), + Importer.Import(E->getRParenLoc())); +} + +Expr *ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + LabelDecl *ToLabel = cast_or_null<LabelDecl>(Importer.Import(E->getLabel())); + if (!ToLabel) + return nullptr; + + return new (Importer.getToContext()) AddrLabelExpr( + Importer.Import(E->getAmpAmpLoc()), Importer.Import(E->getLabelLoc()), + ToLabel, T); +} + Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Expr *SubExpr = Importer.Import(E->getSubExpr()); if (!SubExpr) @@ -5103,6 +5578,31 @@ Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) { SubExpr); } +Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) { + SmallVector<Expr *, 4> Exprs(E->getNumExprs()); + if (ImportArrayChecked( + E->getExprs(), E->getExprs() + E->getNumExprs(), Exprs.begin())) + return nullptr; + + return new (Importer.getToContext()) ParenListExpr( + Importer.getToContext(), Importer.Import(E->getLParenLoc()), + Exprs, Importer.Import(E->getLParenLoc())); +} + +Expr *ASTNodeImporter::VisitStmtExpr(StmtExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + CompoundStmt *ToSubStmt = cast_or_null<CompoundStmt>( + Importer.Import(E->getSubStmt())); + if (!ToSubStmt && E->getSubStmt()) + return nullptr; + + return new (Importer.getToContext()) StmtExpr(ToSubStmt, T, + Importer.Import(E->getLParenLoc()), Importer.Import(E->getRParenLoc())); +} + Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5163,6 +5663,76 @@ Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { E->isFPContractable()); } +Expr *ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *ToLHS = Importer.Import(E->getLHS()); + if (!ToLHS) + return nullptr; + + Expr *ToRHS = Importer.Import(E->getRHS()); + if (!ToRHS) + return nullptr; + + Expr *ToCond = Importer.Import(E->getCond()); + if (!ToCond) + return nullptr; + + return new (Importer.getToContext()) ConditionalOperator( + ToCond, Importer.Import(E->getQuestionLoc()), + ToLHS, Importer.Import(E->getColonLoc()), + ToRHS, T, E->getValueKind(), E->getObjectKind()); +} + +Expr *ASTNodeImporter::VisitBinaryConditionalOperator( + BinaryConditionalOperator *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *Common = Importer.Import(E->getCommon()); + if (!Common) + return nullptr; + + Expr *Cond = Importer.Import(E->getCond()); + if (!Cond) + return nullptr; + + OpaqueValueExpr *OpaqueValue = cast_or_null<OpaqueValueExpr>( + Importer.Import(E->getOpaqueValue())); + if (!OpaqueValue) + return nullptr; + + Expr *TrueExpr = Importer.Import(E->getTrueExpr()); + if (!TrueExpr) + return nullptr; + + Expr *FalseExpr = Importer.Import(E->getFalseExpr()); + if (!FalseExpr) + return nullptr; + + return new (Importer.getToContext()) BinaryConditionalOperator( + Common, OpaqueValue, Cond, TrueExpr, FalseExpr, + Importer.Import(E->getQuestionLoc()), Importer.Import(E->getColonLoc()), + T, E->getValueKind(), E->getObjectKind()); +} + +Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *SourceExpr = Importer.Import(E->getSourceExpr()); + if (!SourceExpr && E->getSourceExpr()) + return nullptr; + + return new (Importer.getToContext()) OpaqueValueExpr( + Importer.Import(E->getExprLoc()), T, E->getValueKind(), + E->getObjectKind(), SourceExpr); +} + Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5247,21 +5817,14 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { return nullptr; CXXConstructorDecl *ToCCD = - dyn_cast<CXXConstructorDecl>(Importer.Import(E->getConstructor())); - if (!ToCCD && E->getConstructor()) + dyn_cast_or_null<CXXConstructorDecl>(Importer.Import(E->getConstructor())); + if (!ToCCD) return nullptr; - size_t NumArgs = E->getNumArgs(); - SmallVector<Expr *, 1> ToArgs(NumArgs); - ASTImporter &_Importer = Importer; - std::transform(E->arg_begin(), E->arg_end(), ToArgs.begin(), - [&_Importer](Expr *AE) -> Expr * { - return _Importer.Import(AE); - }); - for (Expr *ToA : ToArgs) { - if (!ToA) - return nullptr; - } + SmallVector<Expr *, 6> ToArgs(E->getNumArgs()); + if (ImportArrayChecked(E->getArgs(), E->getArgs() + E->getNumArgs(), + ToArgs.begin())) + return nullptr; return CXXConstructExpr::Create(Importer.getToContext(), T, Importer.Import(E->getLocation()), @@ -5274,6 +5837,44 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { Importer.Import(E->getParenOrBraceRange())); } +Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *ToFn = Importer.Import(E->getCallee()); + if (!ToFn) + return nullptr; + + SmallVector<Expr *, 4> ToArgs(E->getNumArgs()); + + if (ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin())) + return nullptr; + + return new (Importer.getToContext()) CXXMemberCallExpr( + Importer.getToContext(), ToFn, ToArgs, T, E->getValueKind(), + Importer.Import(E->getRParenLoc())); +} + +Expr *ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + return new (Importer.getToContext()) + CXXThisExpr(Importer.Import(E->getLocation()), T, E->isImplicit()); +} + +Expr *ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + return new (Importer.getToContext()) + CXXBoolLiteralExpr(E->getValue(), T, Importer.Import(E->getLocation())); +} + + Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5342,6 +5943,95 @@ Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) { Importer.Import(E->getRParenLoc())); } +Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { + QualType T = Importer.Import(ILE->getType()); + if (T.isNull()) + return nullptr; + + llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits()); + if (ImportArrayChecked( + ILE->getInits(), ILE->getInits() + ILE->getNumInits(), Exprs.begin())) + return nullptr; + + ASTContext &ToCtx = Importer.getToContext(); + InitListExpr *To = new (ToCtx) InitListExpr( + ToCtx, Importer.Import(ILE->getLBraceLoc()), + Exprs, Importer.Import(ILE->getLBraceLoc())); + To->setType(T); + + if (ILE->hasArrayFiller()) { + Expr *Filler = Importer.Import(ILE->getArrayFiller()); + if (!Filler) + return nullptr; + To->setArrayFiller(Filler); + } + + if (FieldDecl *FromFD = ILE->getInitializedFieldInUnion()) { + FieldDecl *ToFD = cast_or_null<FieldDecl>(Importer.Import(FromFD)); + if (!ToFD) + return nullptr; + To->setInitializedFieldInUnion(ToFD); + } + + if (InitListExpr *SyntForm = ILE->getSyntacticForm()) { + InitListExpr *ToSyntForm = cast_or_null<InitListExpr>( + Importer.Import(SyntForm)); + if (!ToSyntForm) + return nullptr; + To->setSyntacticForm(ToSyntForm); + } + + To->sawArrayRangeDesignator(ILE->hadArrayRangeDesignator()); + To->setValueDependent(ILE->isValueDependent()); + To->setInstantiationDependent(ILE->isInstantiationDependent()); + + return To; +} + +Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { + FieldDecl *ToField = llvm::dyn_cast_or_null<FieldDecl>( + Importer.Import(DIE->getField())); + if (!ToField && DIE->getField()) + return nullptr; + + return CXXDefaultInitExpr::Create( + Importer.getToContext(), Importer.Import(DIE->getLocStart()), ToField); +} + +Expr *ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { + QualType ToType = Importer.Import(E->getType()); + if (ToType.isNull() && !E->getType().isNull()) + return nullptr; + ExprValueKind VK = E->getValueKind(); + CastKind CK = E->getCastKind(); + Expr *ToOp = Importer.Import(E->getSubExpr()); + if (!ToOp && E->getSubExpr()) + return nullptr; + CXXCastPath BasePath; + if (ImportCastPath(E, BasePath)) + return nullptr; + TypeSourceInfo *ToWritten = Importer.Import(E->getTypeInfoAsWritten()); + SourceLocation ToOperatorLoc = Importer.Import(E->getOperatorLoc()); + SourceLocation ToRParenLoc = Importer.Import(E->getRParenLoc()); + SourceRange ToAngleBrackets = Importer.Import(E->getAngleBrackets()); + + if (isa<CXXStaticCastExpr>(E)) { + return CXXStaticCastExpr::Create( + Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath, + ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); + } else if (isa<CXXDynamicCastExpr>(E)) { + return CXXDynamicCastExpr::Create( + Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath, + ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); + } else if (isa<CXXReinterpretCastExpr>(E)) { + return CXXReinterpretCastExpr::Create( + Importer.getToContext(), ToType, VK, CK, ToOp, &BasePath, + ToWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); + } else { + return nullptr; + } +} + ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTContext &FromContext, FileManager &FromFileManager, bool MinimalImport) @@ -5747,6 +6437,72 @@ FileID ASTImporter::Import(FileID FromID) { return ToID; } +CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { + Expr *ToExpr = Import(From->getInit()); + if (!ToExpr && From->getInit()) + return nullptr; + + if (From->isBaseInitializer()) { + TypeSourceInfo *ToTInfo = Import(From->getTypeSourceInfo()); + if (!ToTInfo && From->getTypeSourceInfo()) + return nullptr; + + return new (ToContext) CXXCtorInitializer( + ToContext, ToTInfo, From->isBaseVirtual(), Import(From->getLParenLoc()), + ToExpr, Import(From->getRParenLoc()), + From->isPackExpansion() ? Import(From->getEllipsisLoc()) + : SourceLocation()); + } else if (From->isMemberInitializer()) { + FieldDecl *ToField = + llvm::cast_or_null<FieldDecl>(Import(From->getMember())); + if (!ToField && From->getMember()) + return nullptr; + + return new (ToContext) CXXCtorInitializer( + ToContext, ToField, Import(From->getMemberLocation()), + Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc())); + } else if (From->isIndirectMemberInitializer()) { + IndirectFieldDecl *ToIField = llvm::cast_or_null<IndirectFieldDecl>( + Import(From->getIndirectMember())); + if (!ToIField && From->getIndirectMember()) + return nullptr; + + return new (ToContext) CXXCtorInitializer( + ToContext, ToIField, Import(From->getMemberLocation()), + Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc())); + } else if (From->isDelegatingInitializer()) { + TypeSourceInfo *ToTInfo = Import(From->getTypeSourceInfo()); + if (!ToTInfo && From->getTypeSourceInfo()) + return nullptr; + + return new (ToContext) + CXXCtorInitializer(ToContext, ToTInfo, Import(From->getLParenLoc()), + ToExpr, Import(From->getRParenLoc())); + } else if (unsigned NumArrayIndices = From->getNumArrayIndices()) { + FieldDecl *ToField = + llvm::cast_or_null<FieldDecl>(Import(From->getMember())); + if (!ToField && From->getMember()) + return nullptr; + + SmallVector<VarDecl *, 4> ToAIs(NumArrayIndices); + + for (unsigned AII = 0; AII < NumArrayIndices; ++AII) { + VarDecl *ToArrayIndex = + dyn_cast_or_null<VarDecl>(Import(From->getArrayIndex(AII))); + if (!ToArrayIndex && From->getArrayIndex(AII)) + return nullptr; + } + + return CXXCtorInitializer::Create( + ToContext, ToField, Import(From->getMemberLocation()), + Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc()), + ToAIs.data(), NumArrayIndices); + } else { + return nullptr; + } +} + + void ASTImporter::ImportDefinition(Decl *From) { Decl *To = Import(From); if (!To) @@ -5851,7 +6607,12 @@ IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { if (!FromId) return nullptr; - return &ToContext.Idents.get(FromId->getName()); + IdentifierInfo *ToId = &ToContext.Idents.get(FromId->getName()); + + if (!ToId->getBuiltinID() && FromId->getBuiltinID()) + ToId->setBuiltinID(FromId->getBuiltinID()); + + return ToId; } Selector ASTImporter::Import(Selector FromSel) { @@ -5910,6 +6671,16 @@ void ASTImporter::CompleteDecl (Decl *D) { } Decl *ASTImporter::Imported(Decl *From, Decl *To) { + if (From->hasAttrs()) { + for (Attr *FromAttr : From->getAttrs()) + To->addAttr(FromAttr->clone(To->getASTContext())); + } + if (From->isUsed()) { + To->setIsUsed(); + } + if (From->isImplicit()) { + To->setImplicit(); + } ImportedDecls[From] = To; return To; } diff --git a/lib/AST/ASTTypeTraits.cpp b/lib/AST/ASTTypeTraits.cpp index ec0671ceb1b5..2336c98fe049 100644 --- a/lib/AST/ASTTypeTraits.cpp +++ b/lib/AST/ASTTypeTraits.cpp @@ -22,12 +22,12 @@ namespace ast_type_traits { const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { { NKI_None, "<None>" }, - { NKI_None, "CXXCtorInitializer" }, { NKI_None, "TemplateArgument" }, - { NKI_None, "NestedNameSpecifier" }, { NKI_None, "NestedNameSpecifierLoc" }, { NKI_None, "QualType" }, { NKI_None, "TypeLoc" }, + { NKI_None, "CXXCtorInitializer" }, + { NKI_None, "NestedNameSpecifier" }, { NKI_None, "Decl" }, #define DECL(DERIVED, BASE) { NKI_##BASE, #DERIVED "Decl" }, #include "clang/AST/DeclNodes.inc" @@ -43,10 +43,6 @@ bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { return isBaseOf(KindId, Other.KindId, Distance); } -bool ASTNodeKind::isSame(ASTNodeKind Other) const { - return KindId != NKI_None && KindId == Other.KindId; -} - bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance) { if (Base == NKI_None || Derived == NKI_None) return false; diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index 6785a0c2935a..6a6ca76a0165 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -405,6 +405,21 @@ bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, return false; } +bool CXXRecordDecl::FindOMPReductionMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + DeclarationName Name) { + RecordDecl *BaseRecord = + Specifier->getType()->castAs<RecordType>()->getDecl(); + + for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + if (Path.Decls.front()->isInIdentifierNamespace(IDNS_OMPReduction)) + return true; + } + + return false; +} + bool CXXRecordDecl:: FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index d05c5de543ff..893bdc5c17bf 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -157,7 +157,7 @@ void DeclInfo::fill() { case Decl::CXXConversion: { const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl); Kind = FunctionKind; - ParamVars = llvm::makeArrayRef(FD->param_begin(), FD->getNumParams()); + ParamVars = FD->parameters(); ReturnType = FD->getReturnType(); unsigned NumLists = FD->getNumTemplateParameterLists(); if (NumLists != 0) { @@ -177,7 +177,7 @@ void DeclInfo::fill() { case Decl::ObjCMethod: { const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl); Kind = FunctionKind; - ParamVars = llvm::makeArrayRef(MD->param_begin(), MD->param_size()); + ParamVars = MD->parameters(); ReturnType = MD->getReturnType(); IsObjCMethod = true; IsInstanceMethod = MD->isInstanceMethod(); @@ -189,7 +189,7 @@ void DeclInfo::fill() { Kind = FunctionKind; TemplateKind = Template; const FunctionDecl *FD = FTD->getTemplatedDecl(); - ParamVars = llvm::makeArrayRef(FD->param_begin(), FD->getNumParams()); + ParamVars = FD->parameters(); ReturnType = FD->getReturnType(); TemplateParameters = FTD->getTemplateParameters(); break; diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp index 98b7e367950c..57bfef08df6e 100644 --- a/lib/AST/CommentLexer.cpp +++ b/lib/AST/CommentLexer.cpp @@ -1,3 +1,12 @@ +//===--- CommentLexer.cpp -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + #include "clang/AST/CommentLexer.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/CommentDiagnostic.h" @@ -44,7 +53,7 @@ namespace { #include "clang/AST/CommentHTMLTags.inc" #include "clang/AST/CommentHTMLNamedCharacterReferences.inc" -} // unnamed namespace +} // end anonymous namespace StringRef Lexer::resolveHTMLNamedCharacterReference(StringRef Name) const { // Fast path, first check a few most widely used named character references. @@ -266,7 +275,7 @@ const char *findCCommentEnd(const char *BufferPtr, const char *BufferEnd) { llvm_unreachable("buffer end hit before '*/' was seen"); } -} // unnamed namespace +} // end anonymous namespace void Lexer::formTokenWithChars(Token &Result, const char *TokEnd, tok::TokenKind Kind) { @@ -411,7 +420,6 @@ void Lexer::lexCommentText(Token &T) { setupAndLexHTMLEndTag(T); else formTextToken(T, TokenPtr); - return; } @@ -604,7 +612,6 @@ void Lexer::lexHTMLCharacterReference(Token &T) { } formTokenWithChars(T, TokenPtr, tok::text); T.setText(Resolved); - return; } void Lexer::setupAndLexHTMLStartTag(Token &T) { @@ -848,4 +855,3 @@ StringRef Lexer::getSpelling(const Token &Tok, } // end namespace comments } // end namespace clang - diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index 12823c37dfc6..f5f4f70dcbbf 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -23,7 +23,7 @@ namespace comments { namespace { #include "clang/AST/CommentHTMLTagsProperties.inc" -} // unnamed namespace +} // end anonymous namespace Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, DiagnosticsEngine &Diags, CommandTraits &Traits, @@ -353,8 +353,6 @@ void Sema::actOnTParamCommandParamNameArg(TParamCommandComment *Command, << CorrectedName << FixItHint::CreateReplacement(ArgRange, CorrectedName); } - - return; } void Sema::actOnTParamCommandFinish(TParamCommandComment *Command, @@ -1002,7 +1000,7 @@ void SimpleTypoCorrector::addDecl(const NamedDecl *ND) { BestIndex = CurrIndex; } } -} // unnamed namespace +} // end anonymous namespace unsigned Sema::correctTypoInParmVarReference( StringRef Typo, @@ -1040,7 +1038,7 @@ bool ResolveTParamReferenceHelper( } return false; } -} // unnamed namespace +} // end anonymous namespace bool Sema::resolveTParamReference( StringRef Name, @@ -1067,7 +1065,7 @@ void CorrectTypoInTParamReferenceHelper( Corrector); } } -} // unnamed namespace +} // end anonymous namespace StringRef Sema::correctTypoInTParamReference( StringRef Typo, @@ -1095,4 +1093,3 @@ Sema::getInlineCommandRenderKind(StringRef Name) const { } // end namespace comments } // end namespace clang - diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 427ca5efcd69..d1e8d25ea044 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -18,6 +18,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -221,7 +222,7 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D, // implies visibility(default). if (D->getASTContext().getTargetInfo().getTriple().isOSDarwin()) { for (const auto *A : D->specific_attrs<AvailabilityAttr>()) - if (A->getPlatform()->getName().equals("macosx")) + if (A->getPlatform()->getName().equals("macos")) return DefaultVisibility; } @@ -591,12 +592,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (Var->getStorageClass() == SC_Static) return LinkageInfo::internal(); - // - a non-volatile object or reference that is explicitly declared const - // or constexpr and neither explicitly declared extern nor previously - // declared to have external linkage; or (there is no equivalent in C99) + // - a non-inline, non-volatile object or reference that is explicitly + // declared const or constexpr and neither explicitly declared extern + // nor previously declared to have external linkage; or (there is no + // equivalent in C99) if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() && - !Var->getType().isVolatileQualified()) { + !Var->getType().isVolatileQualified() && + !Var->isInline()) { const VarDecl *PrevVar = Var->getPreviousDecl(); if (PrevVar) return getLVForDecl(PrevVar, computation); @@ -1421,16 +1424,13 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, Ctx = Ctx->getParent(); } - for (ContextsTy::reverse_iterator I = Contexts.rbegin(), E = Contexts.rend(); - I != E; ++I) { - if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(*I)) { + for (const DeclContext *DC : reverse(Contexts)) { + if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { OS << Spec->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList(OS, - TemplateArgs.data(), - TemplateArgs.size(), - P); - } else if (const auto *ND = dyn_cast<NamespaceDecl>(*I)) { + TemplateSpecializationType::PrintTemplateArgumentList( + OS, TemplateArgs.asArray(), P); + } else if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) { if (P.SuppressUnwrittenScope && (ND->isAnonymousNamespace() || ND->isInline())) continue; @@ -1440,12 +1440,12 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, } else OS << *ND; - } else if (const auto *RD = dyn_cast<RecordDecl>(*I)) { + } else if (const auto *RD = dyn_cast<RecordDecl>(DC)) { if (!RD->getIdentifier()) OS << "(anonymous " << RD->getKindName() << ')'; else OS << *RD; - } else if (const auto *FD = dyn_cast<FunctionDecl>(*I)) { + } else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) { const FunctionProtoType *FT = nullptr; if (FD->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>()); @@ -1466,7 +1466,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, } } OS << ')'; - } else if (const auto *ED = dyn_cast<EnumDecl>(*I)) { + } else if (const auto *ED = dyn_cast<EnumDecl>(DC)) { // 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 @@ -1476,7 +1476,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, else continue; } else { - OS << *cast<NamedDecl>(*I); + OS << *cast<NamedDecl>(DC); } OS << "::"; } @@ -1912,7 +1912,9 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { // C++ [basic.def]p2: // A declaration is a definition unless [...] it contains the 'extern' // specifier or a linkage-specification and neither an initializer [...], - // it declares a static data member in a class declaration [...]. + // it declares a non-inline static data member in a class declaration [...], + // it declares a static data member outside a class definition and the variable + // was defined within the class with the constexpr specifier [...], // C++1y [temp.expl.spec]p15: // An explicit specialization of a static data member or an explicit // specialization of a static data member template is a definition if the @@ -1922,6 +1924,8 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { // a static data member template outside the containing class? if (isStaticDataMember()) { if (isOutOfLine() && + !(getCanonicalDecl()->isInline() && + getCanonicalDecl()->isConstexpr()) && (hasInit() || // If the first declaration is out-of-line, this may be an // instantiation of an out-of-line partial specialization of a variable @@ -1932,6 +1936,8 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { TSK_ExplicitSpecialization) || isa<VarTemplatePartialSpecializationDecl>(this))) return Definition; + else if (!isOutOfLine() && isInline()) + return Definition; else return DeclarationOnly; } @@ -1945,7 +1951,7 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const { if (hasInit()) return Definition; - if (hasAttr<AliasAttr>()) + if (hasDefiningAttr()) return Definition; if (const auto *SAA = getAttr<SelectAnyAttr>()) @@ -2072,18 +2078,6 @@ bool VarDecl::isOutOfLine() const { return false; } -VarDecl *VarDecl::getOutOfLineDefinition() { - if (!isStaticDataMember()) - return nullptr; - - for (auto RD : redecls()) { - if (RD->getLexicalDeclContext()->isFileContext()) - return RD; - } - - return nullptr; -} - void VarDecl::setInit(Expr *I) { if (auto *Eval = Init.dyn_cast<EvaluatedStmt *>()) { Eval->~EvaluatedStmt(); @@ -2448,7 +2442,7 @@ void FunctionDecl::getNameForDiagnostic( const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs(); if (TemplateArgs) TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs->data(), TemplateArgs->size(), Policy); + OS, TemplateArgs->asArray(), Policy); } bool FunctionDecl::isVariadic() const { @@ -2485,7 +2479,7 @@ bool FunctionDecl::hasTrivialBody() const bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { for (auto I : redecls()) { if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed || - I->hasAttr<AliasAttr>()) { + I->hasDefiningAttr()) { Definition = I->IsDeleted ? I->getCanonicalDecl() : I; return true; } @@ -2708,8 +2702,7 @@ unsigned FunctionDecl::getBuiltinID() const { // declaration, for instance "extern "C" { namespace std { decl } }". if (!LinkageDecl) { if (BuiltinID == Builtin::BI__GetExceptionInfo && - Context.getTargetInfo().getCXXABI().isMicrosoft() && - isInStdNamespace()) + Context.getTargetInfo().getCXXABI().isMicrosoft()) return Builtin::BI__GetExceptionInfo; return 0; } @@ -2733,6 +2726,12 @@ unsigned FunctionDecl::getBuiltinID() const { if (getStorageClass() == SC_Static) return 0; + // OpenCL v1.2 s6.9.f - The library functions defined in + // the C99 standard headers are not available. + if (Context.getLangOpts().OpenCL && + Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + return 0; + return BuiltinID; } @@ -2788,7 +2787,7 @@ unsigned FunctionDecl::getMinRequiredArguments() const { return getNumParams(); unsigned NumRequiredArgs = 0; - for (auto *Param : params()) + for (auto *Param : parameters()) if (!Param->isParameterPack() && !Param->hasDefaultArg()) ++NumRequiredArgs; return NumRequiredArgs; @@ -2929,16 +2928,22 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const { return RTRange; } -bool FunctionDecl::hasUnusedResultAttr() const { +const Attr *FunctionDecl::getUnusedResultAttr() const { QualType RetType = getReturnType(); if (RetType->isRecordType()) { const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl(); const auto *MD = dyn_cast<CXXMethodDecl>(this); - if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() && - !(MD && MD->getCorrespondingMethodInClass(Ret, true))) - return true; + if (Ret && !(MD && MD->getCorrespondingMethodInClass(Ret, true))) { + if (const auto *R = Ret->getAttr<WarnUnusedResultAttr>()) + return R; + } + } else if (const auto *ET = RetType->getAs<EnumType>()) { + if (const EnumDecl *ED = ET->getDecl()) { + if (const auto *R = ED->getAttr<WarnUnusedResultAttr>()) + return R; + } } - return hasAttr<WarnUnusedResultAttr>(); + return getAttr<WarnUnusedResultAttr>(); } /// \brief For an inline function definition in C, or for a gnu_inline function @@ -3520,6 +3525,7 @@ SourceLocation TagDecl::getOuterLocStart() const { } SourceRange TagDecl::getSourceRange() const { + SourceLocation RBraceLoc = BraceRange.getEnd(); SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation(); return SourceRange(getOuterLocStart(), E); } @@ -3675,6 +3681,21 @@ void EnumDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, MSI->setPointOfInstantiation(PointOfInstantiation); } +EnumDecl *EnumDecl::getTemplateInstantiationPattern() const { + if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) { + if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) { + EnumDecl *ED = getInstantiatedFromMemberEnum(); + while (auto *NewED = ED->getInstantiatedFromMemberEnum()) + ED = NewED; + return ED; + } + } + + assert(!isTemplateInstantiation(getTemplateSpecializationKind()) && + "couldn't find pattern for enum instantiation"); + return nullptr; +} + EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const { if (SpecializationInfo) return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom()); @@ -3900,6 +3921,53 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C); } +void PragmaCommentDecl::anchor() { } + +PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C, + TranslationUnitDecl *DC, + SourceLocation CommentLoc, + PragmaMSCommentKind CommentKind, + StringRef Arg) { + PragmaCommentDecl *PCD = + new (C, DC, additionalSizeToAlloc<char>(Arg.size() + 1)) + PragmaCommentDecl(DC, CommentLoc, CommentKind); + memcpy(PCD->getTrailingObjects<char>(), Arg.data(), Arg.size()); + PCD->getTrailingObjects<char>()[Arg.size()] = '\0'; + return PCD; +} + +PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C, + unsigned ID, + unsigned ArgSize) { + return new (C, ID, additionalSizeToAlloc<char>(ArgSize + 1)) + PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown); +} + +void PragmaDetectMismatchDecl::anchor() { } + +PragmaDetectMismatchDecl * +PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC, + SourceLocation Loc, StringRef Name, + StringRef Value) { + size_t ValueStart = Name.size() + 1; + PragmaDetectMismatchDecl *PDMD = + new (C, DC, additionalSizeToAlloc<char>(ValueStart + Value.size() + 1)) + PragmaDetectMismatchDecl(DC, Loc, ValueStart); + memcpy(PDMD->getTrailingObjects<char>(), Name.data(), Name.size()); + PDMD->getTrailingObjects<char>()[Name.size()] = '\0'; + memcpy(PDMD->getTrailingObjects<char>() + ValueStart, Value.data(), + Value.size()); + PDMD->getTrailingObjects<char>()[ValueStart + Value.size()] = '\0'; + return PDMD; +} + +PragmaDetectMismatchDecl * +PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NameValueSize) { + return new (C, ID, additionalSizeToAlloc<char>(NameValueSize + 1)) + PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0); +} + void ExternCContextDecl::anchor() { } ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C, @@ -4026,8 +4094,10 @@ 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) { + QualType T, + MutableArrayRef<NamedDecl *> CH) + : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH.data()), + ChainingSize(CH.size()) { // 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) @@ -4036,16 +4106,15 @@ IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC, IndirectFieldDecl * IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, NamedDecl **CH, - unsigned CHS) { - return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH, CHS); + IdentifierInfo *Id, QualType T, + llvm::MutableArrayRef<NamedDecl *> CH) { + return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH); } IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(), - DeclarationName(), QualType(), nullptr, - 0); + DeclarationName(), QualType(), None); } SourceRange EnumConstantDecl::getSourceRange() const { diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 72587e388e47..bfb7d02b2955 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -46,7 +46,7 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const { } #define DECL(DERIVED, BASE) \ - static_assert(Decl::DeclObjAlignment >= \ + static_assert(llvm::AlignOf<Decl>::Alignment >= \ llvm::AlignOf<DERIVED##Decl>::Alignment, \ "Alignment sufficient after objects prepended to " #DERIVED); #define ABSTRACT_DECL(DECL) @@ -56,7 +56,7 @@ 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. - static_assert(sizeof(unsigned) * 2 >= DeclObjAlignment, + static_assert(sizeof(unsigned) * 2 >= llvm::AlignOf<Decl>::Alignment, "Decl won't be misaligned"); void *Start = Context.Allocate(Size + Extra + 8); void *Result = (char*)Start + 8; @@ -81,7 +81,8 @@ void *Decl::operator new(std::size_t Size, const ASTContext &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); + llvm::OffsetToAlignment(sizeof(Module *), + llvm::AlignOf<Decl>::Alignment); char *Buffer = reinterpret_cast<char *>( ::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx)); Buffer += ExtraAlign; @@ -196,6 +197,17 @@ bool Decl::isTemplateDecl() const { return isa<TemplateDecl>(this); } +TemplateDecl *Decl::getDescribedTemplate() const { + if (auto *FD = dyn_cast<FunctionDecl>(this)) + return FD->getDescribedFunctionTemplate(); + else if (auto *RD = dyn_cast<CXXRecordDecl>(this)) + return RD->getDescribedClassTemplate(); + else if (auto *VD = dyn_cast<VarDecl>(this)) + return VD->getDescribedVarTemplate(); + + return nullptr; +} + const DeclContext *Decl::getParentFunctionOrMethod() const { for (const DeclContext *DC = getDeclContext(); DC && !DC->isTranslationUnit() && !DC->isNamespace(); @@ -329,25 +341,29 @@ unsigned Decl::getMaxAlignment() const { return Align; } -bool Decl::isUsed(bool CheckUsedAttr) const { - if (Used) +bool Decl::isUsed(bool CheckUsedAttr) const { + const Decl *CanonD = getCanonicalDecl(); + if (CanonD->Used) return true; - + // Check for used attribute. - if (CheckUsedAttr && hasAttr<UsedAttr>()) + // Ask the most recent decl, since attributes accumulate in the redecl chain. + if (CheckUsedAttr && getMostRecentDecl()->hasAttr<UsedAttr>()) return true; - return false; + // The information may have not been deserialized yet. Force deserialization + // to complete the needed information. + return getMostRecentDecl()->getCanonicalDecl()->Used; } void Decl::markUsed(ASTContext &C) { - if (Used) + if (isUsed(false)) return; if (C.getASTMutationListener()) C.getASTMutationListener()->DeclarationMarkedUsed(this); - Used = true; + setIsUsed(); } bool Decl::isReferenced() const { @@ -362,6 +378,18 @@ bool Decl::isReferenced() const { return false; } +bool Decl::hasDefiningAttr() const { + return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>(); +} + +const Attr *Decl::getDefiningAttr() const { + if (AliasAttr *AA = getAttr<AliasAttr>()) + return AA; + if (IFuncAttr *IFA = getAttr<IFuncAttr>()) + return IFA; + return nullptr; +} + /// \brief Determine the availability of the given declaration based on /// the target platform. /// @@ -432,7 +460,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, << VTI << HintMessage; } - return AR_NotYetIntroduced; + return A->getStrict() ? AR_Unavailable : AR_NotYetIntroduced; } // Make sure that this declaration hasn't been obsoleted. @@ -467,6 +495,9 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, } AvailabilityResult Decl::getAvailability(std::string *Message) const { + if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this)) + return FTD->getTemplatedDecl()->getAvailability(Message); + AvailabilityResult Result = AR_Available; std::string ResultMessage; @@ -563,6 +594,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Function: case CXXMethod: case CXXConstructor: + case ConstructorUsingShadow: case CXXDestructor: case CXXConversion: case EnumConstant: @@ -630,6 +662,9 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case TemplateTemplateParm: return IDNS_Ordinary | IDNS_Tag | IDNS_Type; + case OMPDeclareReduction: + return IDNS_OMPReduction; + // Never have names. case Friend: case FriendTemplate: @@ -638,6 +673,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case FileScopeAsm: case StaticAssert: case ObjCPropertyImpl: + case PragmaComment: + case PragmaDetectMismatch: case Block: case Captured: case TranslationUnit: @@ -655,6 +692,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCCategoryImpl: case Import: case OMPThreadPrivate: + case OMPCapturedExpr: case Empty: // Never looked up by name. return 0; @@ -957,6 +995,7 @@ DeclContext *DeclContext::getPrimaryContext() { case Decl::LinkageSpec: case Decl::Block: case Decl::Captured: + case Decl::OMPDeclareReduction: // There is only one DeclContext for these entities. return this; @@ -1549,9 +1588,12 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, bool Recoverable) { assert(this == getPrimaryContext() && "expected a primary DC"); - // Skip declarations within functions. - if (isFunctionOrMethod()) + if (!isLookupContext()) { + if (isTransparentContext()) + getParent()->getPrimaryContext() + ->makeDeclVisibleInContextWithFlags(D, Internal, Recoverable); return; + } // Skip declarations which should be invisible to name lookup. if (shouldBeHidden(D)) diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 4f24fdc28f71..d069bfdc3dc2 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -46,34 +46,33 @@ void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const { } CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) - : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0), - Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), - Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), - HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), - HasMutableFields(false), HasVariantMembers(false), HasOnlyCMembers(true), - HasInClassInitializer(false), HasUninitializedReferenceMember(false), - NeedOverloadResolutionForMoveConstructor(false), - NeedOverloadResolutionForMoveAssignment(false), - NeedOverloadResolutionForDestructor(false), - DefaultedMoveConstructorIsDeleted(false), - DefaultedMoveAssignmentIsDeleted(false), - DefaultedDestructorIsDeleted(false), - HasTrivialSpecialMembers(SMF_All), - DeclaredNonTrivialSpecialMembers(0), - HasIrrelevantDestructor(true), - HasConstexprNonCopyMoveConstructor(false), - DefaultedDefaultConstructorIsConstexpr(true), - HasConstexprDefaultConstructor(false), - HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false), - UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0), - ImplicitCopyConstructorHasConstParam(true), - ImplicitCopyAssignmentHasConstParam(true), - HasDeclaredCopyConstructorWithConstParam(false), - HasDeclaredCopyAssignmentWithConstParam(false), - IsLambda(false), IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), - Bases(), VBases(), - Definition(D), FirstFriend() { -} + : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0), + Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), + Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), + HasPrivateFields(false), HasProtectedFields(false), + HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false), + HasOnlyCMembers(true), HasInClassInitializer(false), + HasUninitializedReferenceMember(false), HasUninitializedFields(false), + HasInheritedConstructor(false), HasInheritedAssignment(false), + NeedOverloadResolutionForMoveConstructor(false), + NeedOverloadResolutionForMoveAssignment(false), + NeedOverloadResolutionForDestructor(false), + DefaultedMoveConstructorIsDeleted(false), + DefaultedMoveAssignmentIsDeleted(false), + DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All), + DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true), + HasConstexprNonCopyMoveConstructor(false), + HasDefaultedDefaultConstructor(false), + DefaultedDefaultConstructorIsConstexpr(true), + HasConstexprDefaultConstructor(false), + HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false), + UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0), + ImplicitCopyConstructorHasConstParam(true), + ImplicitCopyAssignmentHasConstParam(true), + HasDeclaredCopyConstructorWithConstParam(false), + HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false), + IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), Bases(), + VBases(), Definition(D), FirstFriend() {} CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { return Bases.get(Definition->getASTContext().getExternalSource()); @@ -89,7 +88,7 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, CXXRecordDecl *PrevDecl) : RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl), DefinitionData(PrevDecl ? PrevDecl->DefinitionData - : DefinitionDataPtr(this)), + : nullptr), TemplateOrInstantiation() {} CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, @@ -143,9 +142,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, C.Deallocate(data().getBases()); if (NumBases) { - // C++ [dcl.init.aggr]p1: - // An aggregate is [...] a class with [...] no base classes [...]. - data().Aggregate = false; + if (!C.getLangOpts().CPlusPlus1z) { + // C++ [dcl.init.aggr]p1: + // An aggregate is [...] a class with [...] no base classes [...]. + data().Aggregate = false; + } // C++ [class]p4: // A POD-struct is an aggregate class... @@ -171,8 +172,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); - // A class with a non-empty base class is not empty. - // FIXME: Standard ref? if (!BaseClassDecl->isEmpty()) { if (!data().Empty) { // C++0x [class]p7: @@ -186,10 +185,18 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().IsStandardLayout = false; } + // C++14 [meta.unary.prop]p4: + // T is a class type [...] with [...] no base class B for which + // is_empty<B>::value is false. data().Empty = false; data().HasNoNonEmptyBases = false; } + // C++1z [dcl.init.agg]p1: + // An aggregate is a class with [...] no private or protected base classes + if (Base->getAccessSpecifier() != AS_public) + data().Aggregate = false; + // C++ [class.virtual]p1: // A class that declares or inherits a virtual function is called a // polymorphic class. @@ -220,6 +227,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (CXXRecordDecl *VBaseDecl = VBase.getType()->getAsCXXRecordDecl()) if (!VBaseDecl->hasCopyConstructorWithConstParam()) data().ImplicitCopyConstructorHasConstParam = false; + + // C++1z [dcl.init.agg]p1: + // An aggregate is a class with [...] no virtual base classes + data().Aggregate = false; } } @@ -228,11 +239,15 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType)).second) VBases.push_back(Base); - // C++0x [meta.unary.prop] is_empty: - // T is a class type, but not a union type, with ... no virtual base - // classes + // C++14 [meta.unary.prop] is_empty: + // T is a class type, but not a union type, with ... no virtual base + // classes data().Empty = false; + // C++1z [dcl.init.agg]p1: + // An aggregate is a class with [...] no virtual base classes + data().Aggregate = false; + // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: // A [default constructor, copy/move constructor, or copy/move assignment // operator for a class X] is trivial [...] if: @@ -332,6 +347,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (BaseClassDecl->hasUninitializedReferenceMember()) data().HasUninitializedReferenceMember = true; + if (!BaseClassDecl->allowConstDefaultInit()) + data().HasUninitializedFields = true; + addedClassSubobject(BaseClassDecl); } @@ -430,6 +448,15 @@ void CXXRecordDecl::addedMember(Decl *D) { FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D); if (FunTmpl) D = FunTmpl->getTemplatedDecl(); + + // FIXME: Pass NamedDecl* to addedMember? + Decl *DUnderlying = D; + if (auto *ND = dyn_cast<NamedDecl>(DUnderlying)) { + DUnderlying = ND->getUnderlyingDecl(); + if (FunctionTemplateDecl *UnderlyingFunTmpl = + dyn_cast<FunctionTemplateDecl>(DUnderlying)) + DUnderlying = UnderlyingFunTmpl->getTemplatedDecl(); + } if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { if (Method->isVirtual()) { @@ -441,8 +468,8 @@ void CXXRecordDecl::addedMember(Decl *D) { // A POD-struct is an aggregate class... data().PlainOldData = false; - // Virtual functions make the class non-empty. - // FIXME: Standard ref? + // C++14 [meta.unary.prop]p4: + // T is a class type [...] with [...] no virtual member functions... data().Empty = false; // C++ [class.virtual]p1: @@ -485,18 +512,15 @@ void CXXRecordDecl::addedMember(Decl *D) { data().PlainOldData = false; } - // Technically, "user-provided" is only defined for special member - // functions, but the intent of the standard is clearly that it should apply - // to all functions. - bool UserProvided = Constructor->isUserProvided(); - if (Constructor->isDefaultConstructor()) { SMKind |= SMF_DefaultConstructor; - if (UserProvided) + if (Constructor->isUserProvided()) data().UserProvidedDefaultConstructor = true; if (Constructor->isConstexpr()) data().HasConstexprDefaultConstructor = true; + if (Constructor->isDefaulted()) + data().HasDefaultedDefaultConstructor = true; } if (!FunTmpl) { @@ -509,9 +533,17 @@ void CXXRecordDecl::addedMember(Decl *D) { } else if (Constructor->isMoveConstructor()) SMKind |= SMF_MoveConstructor; } + } + // Handle constructors, including those inherited from base classes. + if (CXXConstructorDecl *Constructor = + dyn_cast<CXXConstructorDecl>(DUnderlying)) { // Record if we see any constexpr constructors which are neither copy // nor move constructors. + // C++1z [basic.types]p10: + // [...] has at least one constexpr constructor or constructor template + // (possibly inherited from a base class) that is not a copy or move + // constructor [...] if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) data().HasConstexprNonCopyMoveConstructor = true; @@ -521,8 +553,12 @@ void CXXRecordDecl::addedMember(Decl *D) { // C++11 [dcl.init.aggr]p1: // An aggregate is an array or a class with no user-provided // constructors [...]. + // C++11 [dcl.init.aggr]p1: + // An aggregate is an array or a class with no user-provided + // constructors (including those inherited from a base class) [...]. if (getASTContext().getLangOpts().CPlusPlus11 - ? UserProvided : !Constructor->isImplicit()) + ? Constructor->isUserProvided() + : !Constructor->isImplicit()) data().Aggregate = false; } @@ -702,6 +738,15 @@ void CXXRecordDecl::addedMember(Decl *D) { data().IsStandardLayout = false; } + if (!Field->hasInClassInitializer() && !Field->isMutable()) { + if (CXXRecordDecl *FieldType = Field->getType()->getAsCXXRecordDecl()) { + if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit()) + data().HasUninitializedFields = true; + } else { + data().HasUninitializedFields = true; + } + } + // Record if this field is the first non-literal or volatile field or base. if (!T->isLiteralType(Context) || T.isVolatileQualified()) data().HasNonLiteralTypeFieldsOrBases = true; @@ -720,7 +765,7 @@ void CXXRecordDecl::addedMember(Decl *D) { // An aggregate is a [...] class with [...] no // brace-or-equal-initializers for non-static data members. // - // This rule was removed in C++1y. + // This rule was removed in C++14. if (!getASTContext().getLangOpts().CPlusPlus14) data().Aggregate = false; @@ -910,7 +955,9 @@ void CXXRecordDecl::addedMember(Decl *D) { if (!data().HasNoNonEmptyBases) data().IsStandardLayout = false; - // If this is not a zero-length bit-field, then the class is not empty. + // C++14 [meta.unary.prop]p4: + // T is a class type [...] with [...] no non-static data members other + // than bit-fields of length 0... if (data().Empty) { if (!Field->isBitField() || (!Field->getBitWidth()->isTypeDependent() && @@ -928,6 +975,15 @@ void CXXRecordDecl::addedMember(Decl *D) { data().Conversions.get(Ctx).addDecl(Ctx, Shadow, Shadow->getAccess()); } } + + if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) { + if (Using->getDeclName().getNameKind() == + DeclarationName::CXXConstructorName) + data().HasInheritedConstructor = true; + + if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal) + data().HasInheritedAssignment = true; + } } void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { @@ -1595,6 +1651,13 @@ unsigned CXXMethodDecl::size_overridden_methods() const { return getASTContext().overridden_methods_size(this); } +CXXMethodDecl::overridden_method_range +CXXMethodDecl::overridden_methods() const { + if (isa<CXXConstructorDecl>(this)) + return overridden_method_range(nullptr, nullptr); + return getASTContext().overridden_methods(this); +} + QualType CXXMethodDecl::getThisType(ASTContext &C) const { // C++ 9.3.2p1: The type of this in a member function of a class X is X*. // If the member function is declared const, the type of this is const X*, @@ -1606,7 +1669,7 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const { QualType ClassTy = C.getTypeDeclType(getParent()); ClassTy = C.getQualifiedType(ClassTy, - Qualifiers::fromCVRMask(getTypeQualifiers())); + Qualifiers::fromCVRUMask(getTypeQualifiers())); return C.getPointerType(ClassTy); } @@ -1744,11 +1807,15 @@ SourceRange CXXCtorInitializer::getSourceRange() const { void CXXConstructorDecl::anchor() { } -CXXConstructorDecl * -CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) CXXConstructorDecl(C, nullptr, SourceLocation(), - DeclarationNameInfo(), QualType(), - nullptr, false, false, false, false); +CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, + unsigned ID, + bool Inherited) { + unsigned Extra = additionalSizeToAlloc<InheritedConstructor>(Inherited); + auto *Result = new (C, ID, Extra) CXXConstructorDecl( + C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, + false, false, false, false, InheritedConstructor()); + Result->IsInheritingConstructor = Inherited; + return Result; } CXXConstructorDecl * @@ -1757,13 +1824,16 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicit, bool isInline, - bool isImplicitlyDeclared, bool isConstexpr) { + bool isImplicitlyDeclared, bool isConstexpr, + InheritedConstructor Inherited) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); - return new (C, RD) CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, - isExplicit, isInline, - isImplicitlyDeclared, isConstexpr); + unsigned Extra = + additionalSizeToAlloc<InheritedConstructor>(Inherited ? 1 : 0); + return new (C, RD, Extra) CXXConstructorDecl( + C, RD, StartLoc, NameInfo, T, TInfo, isExplicit, isInline, + isImplicitlyDeclared, isConstexpr, Inherited); } CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const { @@ -1878,23 +1948,6 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const { return true; } -const CXXConstructorDecl *CXXConstructorDecl::getInheritedConstructor() const { - // Hack: we store the inherited constructor in the overridden method table - method_iterator It = getASTContext().overridden_methods_begin(this); - if (It == getASTContext().overridden_methods_end(this)) - return nullptr; - - return cast<CXXConstructorDecl>(*It); -} - -void -CXXConstructorDecl::setInheritedConstructor(const CXXConstructorDecl *BaseCtor){ - // Hack: we store the inherited constructor in the overridden method table - assert(getASTContext().overridden_methods_size(this) == 0 && - "Base ctor already set."); - getASTContext().addOverriddenMethod(this, BaseCtor); -} - void CXXDestructorDecl::anchor() { } CXXDestructorDecl * @@ -2090,10 +2143,24 @@ NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void UsingShadowDecl::anchor() { } +UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, + SourceLocation Loc, UsingDecl *Using, + NamedDecl *Target) + : NamedDecl(K, DC, Loc, Using ? Using->getDeclName() : DeclarationName()), + redeclarable_base(C), Underlying(Target), + UsingOrNextShadow(cast<NamedDecl>(Using)) { + if (Target) + IdentifierNamespace = Target->getIdentifierNamespace(); + setImplicit(); +} + +UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, EmptyShell Empty) + : NamedDecl(K, nullptr, SourceLocation(), DeclarationName()), + redeclarable_base(C), Underlying(), UsingOrNextShadow() {} + UsingShadowDecl * UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) UsingShadowDecl(C, nullptr, SourceLocation(), - nullptr, nullptr); + return new (C, ID) UsingShadowDecl(UsingShadow, C, EmptyShell()); } UsingDecl *UsingShadowDecl::getUsingDecl() const { @@ -2104,6 +2171,25 @@ UsingDecl *UsingShadowDecl::getUsingDecl() const { return cast<UsingDecl>(Shadow->UsingOrNextShadow); } +void ConstructorUsingShadowDecl::anchor() { } + +ConstructorUsingShadowDecl * +ConstructorUsingShadowDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation Loc, UsingDecl *Using, + NamedDecl *Target, bool IsVirtual) { + return new (C, DC) ConstructorUsingShadowDecl(C, DC, Loc, Using, Target, + IsVirtual); +} + +ConstructorUsingShadowDecl * +ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) ConstructorUsingShadowDecl(C, EmptyShell()); +} + +CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const { + return getUsingDecl()->getQualifier()->getAsRecordDecl(); +} + void UsingDecl::anchor() { } void UsingDecl::addShadowDecl(UsingShadowDecl *S) { diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 050a0f53f1e5..d2701211beae 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -152,7 +152,8 @@ bool ObjCContainerDecl::HasUserDeclaredSetterMethod( ObjCPropertyDecl * ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, - const IdentifierInfo *propertyID) { + const IdentifierInfo *propertyID, + ObjCPropertyQueryKind queryKind) { // If this context is a hidden protocol definition, don't find any // property. if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(DC)) { @@ -166,15 +167,33 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC, if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) { for (const auto *Ext : IDecl->known_extensions()) if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext, - propertyID)) + propertyID, + queryKind)) return PD; } DeclContext::lookup_result R = DC->lookup(propertyID); + ObjCPropertyDecl *classProp = nullptr; for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) - if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I)) - return PD; + if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(*I)) { + // If queryKind is unknown, we return the instance property if one + // exists; otherwise we return the class property. + if ((queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && + !PD->isClassProperty()) || + (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && + PD->isClassProperty()) || + (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && + !PD->isClassProperty())) + return PD; + + if (PD->isClassProperty()) + classProp = PD; + } + + if (queryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) + // We can't find the instance property, return the class property. + return classProp; return nullptr; } @@ -192,7 +211,8 @@ ObjCPropertyDecl::getDefaultSynthIvarName(ASTContext &Ctx) const { /// FindPropertyDeclaration - Finds declaration of the property given its name /// in 'PropertyId' and returns it. It returns 0, if not found. ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( - const IdentifierInfo *PropertyId) const { + const IdentifierInfo *PropertyId, + ObjCPropertyQueryKind QueryKind) const { // Don't find properties within hidden protocol definitions. if (const ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(this)) { if (const ObjCProtocolDecl *Def = Proto->getDefinition()) @@ -204,13 +224,14 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( // the class itself. if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) { for (const auto *Ext : ClassDecl->visible_extensions()) { - if (auto *P = Ext->FindPropertyDeclaration(PropertyId)) + if (auto *P = Ext->FindPropertyDeclaration(PropertyId, QueryKind)) return P; } } if (ObjCPropertyDecl *PD = - ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId)) + ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId, + QueryKind)) return PD; switch (getKind()) { @@ -219,7 +240,8 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( case Decl::ObjCProtocol: { const ObjCProtocolDecl *PID = cast<ObjCProtocolDecl>(this); for (const auto *I : PID->protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; break; } @@ -228,18 +250,20 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( // 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)) + if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration( + PropertyId, QueryKind)) return P; } // Look through protocols. for (const auto *I : OID->all_referenced_protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; // Finally, check the super class. if (const ObjCInterfaceDecl *superClass = OID->getSuperClass()) - return superClass->FindPropertyDeclaration(PropertyId); + return superClass->FindPropertyDeclaration(PropertyId, QueryKind); break; } case Decl::ObjCCategory: { @@ -247,7 +271,8 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration( // Look through protocols. if (!OCD->IsClassExtension()) for (const auto *I : OCD->protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; break; } @@ -319,7 +344,8 @@ SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const { /// ObjCPropertyDecl * ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( - IdentifierInfo *PropertyId) const { + IdentifierInfo *PropertyId, + ObjCPropertyQueryKind QueryKind) const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) return nullptr; @@ -328,12 +354,14 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( LoadExternalDefinition(); if (ObjCPropertyDecl *PD = - ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId)) + ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId, + QueryKind)) return PD; // Look through protocols. for (const auto *I : all_referenced_protocols()) - if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId)) + if (ObjCPropertyDecl *P = I->FindPropertyDeclaration(PropertyId, + QueryKind)) return P; return nullptr; @@ -342,13 +370,13 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM, PropertyDeclOrder &PO) const { for (auto *Prop : properties()) { - PM[Prop->getIdentifier()] = Prop; + PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; PO.push_back(Prop); } for (const auto *Ext : known_extensions()) { const ObjCCategoryDecl *ClassExt = Ext; for (auto *Prop : ClassExt->properties()) { - PM[Prop->getIdentifier()] = Prop; + PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; PO.push_back(Prop); } } @@ -1206,23 +1234,29 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const { if (NumArgs > 1) return nullptr; - if (!isInstanceMethod()) - return nullptr; - if (isPropertyAccessor()) { const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent()); bool IsGetter = (NumArgs == 0); + bool IsInstance = isInstanceMethod(); /// 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; + if (IsInstance) { + for (const auto *I : Container->instance_properties()) { + Selector NextSel = IsGetter ? I->getGetterName() + : I->getSetterName(); + if (NextSel == Sel) + return I; + } + } else { + for (const auto *I : Container->class_properties()) { + Selector NextSel = IsGetter ? I->getGetterName() + : I->getSetterName(); + if (NextSel == Sel) + return I; + } } return nullptr; @@ -1822,7 +1856,9 @@ void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM, if (const ObjCProtocolDecl *PDecl = getDefinition()) { for (auto *Prop : PDecl->properties()) { // Insert into PM if not there already. - PM.insert(std::make_pair(Prop->getIdentifier(), Prop)); + PM.insert(std::make_pair( + std::make_pair(Prop->getIdentifier(), Prop->isClassProperty()), + Prop)); PO.push_back(Prop); } // Scan through protocol's protocols. @@ -2011,10 +2047,29 @@ FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { /// category \@implementation block. /// ObjCPropertyImplDecl *ObjCImplDecl:: -FindPropertyImplDecl(IdentifierInfo *Id) const { +FindPropertyImplDecl(IdentifierInfo *Id, + ObjCPropertyQueryKind QueryKind) const { + ObjCPropertyImplDecl *ClassPropImpl = nullptr; for (auto *PID : property_impls()) - if (PID->getPropertyDecl()->getIdentifier() == Id) - return PID; + // If queryKind is unknown, we return the instance property if one + // exists; otherwise we return the class property. + if (PID->getPropertyDecl()->getIdentifier() == Id) { + if ((QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown && + !PID->getPropertyDecl()->isClassProperty()) || + (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_class && + PID->getPropertyDecl()->isClassProperty()) || + (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_instance && + !PID->getPropertyDecl()->isClassProperty())) + return PID; + + if (PID->getPropertyDecl()->isClassProperty()) + ClassPropImpl = PID; + } + + if (QueryKind == ObjCPropertyQueryKind::OBJC_PR_query_unknown) + // We can't find the instance property, return the class property. + return ClassPropImpl; + return nullptr; } diff --git a/lib/AST/DeclOpenMP.cpp b/lib/AST/DeclOpenMP.cpp index 493e2cd41226..5b06ce0778a7 100644 --- a/lib/AST/DeclOpenMP.cpp +++ b/lib/AST/DeclOpenMP.cpp @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// /// \file -/// \brief This file implements OMPThreadPrivateDecl class. +/// \brief This file implements OMPThreadPrivateDecl, OMPCapturedExprDecl +/// classes. /// //===----------------------------------------------------------------------===// @@ -52,3 +53,50 @@ void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) { std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr *>()); } +//===----------------------------------------------------------------------===// +// OMPDeclareReductionDecl Implementation. +//===----------------------------------------------------------------------===// + +void OMPDeclareReductionDecl::anchor() {} + +OMPDeclareReductionDecl *OMPDeclareReductionDecl::Create( + ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, + QualType T, OMPDeclareReductionDecl *PrevDeclInScope) { + return new (C, DC) OMPDeclareReductionDecl(OMPDeclareReduction, DC, L, Name, + T, PrevDeclInScope); +} + +OMPDeclareReductionDecl * +OMPDeclareReductionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) OMPDeclareReductionDecl( + OMPDeclareReduction, /*DC=*/nullptr, SourceLocation(), DeclarationName(), + QualType(), /*PrevDeclInScope=*/nullptr); +} + +OMPDeclareReductionDecl *OMPDeclareReductionDecl::getPrevDeclInScope() { + return cast_or_null<OMPDeclareReductionDecl>( + PrevDeclInScope.get(getASTContext().getExternalSource())); +} +const OMPDeclareReductionDecl * +OMPDeclareReductionDecl::getPrevDeclInScope() const { + return cast_or_null<OMPDeclareReductionDecl>( + PrevDeclInScope.get(getASTContext().getExternalSource())); +} + +//===----------------------------------------------------------------------===// +// OMPCapturedExprDecl Implementation. +//===----------------------------------------------------------------------===// + +void OMPCapturedExprDecl::anchor() {} + +OMPCapturedExprDecl *OMPCapturedExprDecl::Create(ASTContext &C, DeclContext *DC, + IdentifierInfo *Id, + QualType T) { + return new (C, DC) OMPCapturedExprDecl(C, DC, Id, T); +} + +OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType()); +} + diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 5c6002d55c0f..7e786990becb 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -92,6 +92,8 @@ namespace { void VisitUsingDecl(UsingDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); + void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); + void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); void PrintTemplateParameters(const TemplateParameterList *Params, const TemplateArgumentList *Args = nullptr); @@ -130,6 +132,8 @@ static QualType GetBaseType(QualType T) { BaseType = VTy->getElementType(); else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>()) BaseType = RTy->getPointeeType(); + else if (const AutoType *ATy = BaseType->getAs<AutoType>()) + BaseType = ATy->getDeducedType(); else llvm_unreachable("Unknown declarator!"); } @@ -158,19 +162,17 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls, ++Begin; PrintingPolicy SubPolicy(Policy); - if (TD && TD->isCompleteDefinition()) { - TD->print(Out, Policy, Indentation); - Out << " "; - SubPolicy.SuppressTag = true; - } bool isFirst = true; for ( ; Begin != End; ++Begin) { if (isFirst) { + if(TD) + SubPolicy.IncludeTagDefinition = true; SubPolicy.SuppressSpecifiers = false; isFirst = false; } else { if (!isFirst) Out << ", "; + SubPolicy.IncludeTagDefinition = false; SubPolicy.SuppressSpecifiers = true; } @@ -244,7 +246,7 @@ void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) { Pack = true; T = PET->getPattern(); } - T.print(Out, Policy, (Pack ? "..." : "") + DeclName); + T.print(Out, Policy, (Pack ? "..." : "") + DeclName, Indentation); } void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) { @@ -333,7 +335,7 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { // FIXME: Need to be able to tell the DeclPrinter when const char *Terminator = nullptr; - if (isa<OMPThreadPrivateDecl>(*D)) + if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D)) Terminator = nullptr; else if (isa<FunctionDecl>(*D) && cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) @@ -358,6 +360,11 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (Terminator) Out << Terminator; Out << "\n"; + + // Declare target attribute is special one, natural spelling for the pragma + // assumes "ending" construct so print it here. + if (D->hasAttr<OMPDeclareTargetDeclAttr>()) + Out << "#pragma omp end declare target\n"; } if (!Decls.empty()) @@ -378,7 +385,8 @@ void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { if (D->isModulePrivate()) Out << "__module_private__ "; } - D->getTypeSourceInfo()->getType().print(Out, Policy, D->getName()); + QualType Ty = D->getTypeSourceInfo()->getType(); + Ty.print(Out, Policy, D->getName(), Indentation); prettyPrintAttributes(D); } @@ -683,7 +691,7 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) { Out << "__module_private__ "; Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()). - stream(Policy, D->getName()); + stream(Policy, D->getName(), Indentation); if (D->isBitField()) { Out << " : "; @@ -707,6 +715,11 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) { void DeclPrinter::VisitVarDecl(VarDecl *D) { prettyPrintPragmas(D); + + QualType T = D->getTypeSourceInfo() + ? D->getTypeSourceInfo()->getType() + : D->getASTContext().getUnqualifiedObjCPointerType(D->getType()); + if (!Policy.SuppressSpecifiers) { StorageClass SC = D->getStorageClass(); if (SC != SC_None) @@ -728,11 +741,13 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { if (D->isModulePrivate()) Out << "__module_private__ "; + + if (D->isConstexpr()) { + Out << "constexpr "; + T.removeLocalConst(); + } } - QualType T = D->getTypeSourceInfo() - ? D->getTypeSourceInfo()->getType() - : D->getASTContext().getUnqualifiedObjCPointerType(D->getType()); printDeclType(T, D->getName()); Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { @@ -751,7 +766,10 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { else if (D->getInitStyle() == VarDecl::CInit) { Out << " = "; } - Init->printPretty(Out, nullptr, Policy, Indentation); + PrintingPolicy SubPolicy(Policy); + SubPolicy.SuppressSpecifiers = false; + SubPolicy.IncludeTagDefinition = false; + Init->printPretty(Out, nullptr, SubPolicy, Indentation); if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) Out << ")"; } @@ -1046,7 +1064,7 @@ void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { std::string name = OMD->getSelector().getAsString(); std::string::size_type pos, lastPos = 0; - for (const auto *PI : OMD->params()) { + for (const auto *PI : OMD->parameters()) { // FIXME: selector is missing here! pos = name.find_first_of(':', lastPos); Out << " " << name.substr(lastPos, pos - lastPos) << ':'; @@ -1298,6 +1316,11 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { } } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_class) { + Out << (first ? ' ' : ',') << "class"; + first = false; + } + (void) first; // Silence dead store warning due to idiomatic code. Out << " )"; } @@ -1358,3 +1381,38 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { } } +void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { + if (!D->isInvalidDecl()) { + Out << "#pragma omp declare reduction ("; + if (D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) { + static const char *const OperatorNames[NUM_OVERLOADED_OPERATORS] = { + nullptr, +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + Spelling, +#include "clang/Basic/OperatorKinds.def" + }; + const char *OpName = + OperatorNames[D->getDeclName().getCXXOverloadedOperator()]; + assert(OpName && "not an overloaded operator"); + Out << OpName; + } else { + assert(D->getDeclName().isIdentifier()); + D->printName(Out); + } + Out << " : "; + D->getType().print(Out, Policy); + Out << " : "; + D->getCombiner()->printPretty(Out, nullptr, Policy, 0); + Out << ")"; + if (auto *Init = D->getInitializer()) { + Out << " initializer("; + Init->printPretty(Out, nullptr, Policy, 0); + Out << ")"; + } + } +} + +void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { + D->getInit()->printPretty(Out, nullptr, Policy, Indentation); +} + diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index de3ebd23ef4f..37943cdd5b7b 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -65,32 +65,29 @@ TemplateParameterList *TemplateParameterList::Create( unsigned TemplateParameterList::getMinRequiredArguments() const { unsigned NumRequiredArgs = 0; - for (iterator P = const_cast<TemplateParameterList *>(this)->begin(), - PEnd = const_cast<TemplateParameterList *>(this)->end(); - P != PEnd; ++P) { - if ((*P)->isTemplateParameterPack()) { - if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) + for (const NamedDecl *P : asArray()) { + if (P->isTemplateParameterPack()) { + if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) if (NTTP->isExpandedParameterPack()) { NumRequiredArgs += NTTP->getNumExpansionTypes(); continue; } - + break; } - - if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { + + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) { if (TTP->hasDefaultArgument()) break; - } else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(*P)) { + } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) { if (NTTP->hasDefaultArgument()) break; - } else if (cast<TemplateTemplateParmDecl>(*P)->hasDefaultArgument()) + } else if (cast<TemplateTemplateParmDecl>(P)->hasDefaultArgument()) break; - + ++NumRequiredArgs; } - + return NumRequiredArgs; } @@ -111,12 +108,10 @@ unsigned TemplateParameterList::getDepth() const { static void AdoptTemplateParameterList(TemplateParameterList *Params, DeclContext *Owner) { - for (TemplateParameterList::iterator P = Params->begin(), - PEnd = Params->end(); - P != PEnd; ++P) { - (*P)->setDeclContext(Owner); - - if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(*P)) + for (NamedDecl *P : *Params) { + P->setDeclContext(Owner); + + if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner); } } @@ -157,8 +152,8 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c } // Update any previous declarations we saw with the common pointer. - for (unsigned I = 0, N = PrevDecls.size(); I != N; ++I) - PrevDecls[I]->Common = Common; + for (const RedeclarableTemplateDecl *Prev : PrevDecls) + Prev->Common = Common; return Common; } @@ -205,44 +200,41 @@ void RedeclarableTemplateDecl::addSpecializationImpl( /// \brief Generate the injected template arguments for the given template /// parameter list, e.g., for the injected-class-name of a class template. static void GenerateInjectedTemplateArgs(ASTContext &Context, - TemplateParameterList *Params, + TemplateParameterList *Params, TemplateArgument *Args) { - for (TemplateParameterList::iterator Param = Params->begin(), - ParamEnd = Params->end(); - Param != ParamEnd; ++Param) { + for (NamedDecl *Param : *Params) { TemplateArgument Arg; - if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { + if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { QualType ArgType = Context.getTypeDeclType(TTP); if (TTP->isParameterPack()) ArgType = Context.getPackExpansionType(ArgType, None); Arg = TemplateArgument(ArgType); - } else if (NonTypeTemplateParmDecl *NTTP = - dyn_cast<NonTypeTemplateParmDecl>(*Param)) { + } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { Expr *E = new (Context) DeclRefExpr(NTTP, /*enclosing*/ false, NTTP->getType().getNonLValueExprType(Context), Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); - + if (NTTP->isParameterPack()) E = new (Context) PackExpansionExpr(Context.DependentTy, E, NTTP->getLocation(), None); Arg = TemplateArgument(E); } else { - TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); + auto *TTP = cast<TemplateTemplateParmDecl>(Param); if (TTP->isParameterPack()) Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>()); else Arg = TemplateArgument(TemplateName(TTP)); } - - if ((*Param)->isTemplateParameterPack()) + + if (Param->isTemplateParameterPack()) Arg = TemplateArgument::CreatePackCopy(Context, Arg); *Args++ = Arg; } } - + //===----------------------------------------------------------------------===// // FunctionTemplateDecl Implementation //===----------------------------------------------------------------------===// @@ -421,23 +413,17 @@ void ClassTemplateDecl::getPartialSpecializations( = getPartialSpecializations(); PS.clear(); PS.reserve(PartialSpecs.size()); - for (llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl>::iterator - P = PartialSpecs.begin(), PEnd = PartialSpecs.end(); - P != PEnd; ++P) - PS.push_back(P->getMostRecentDecl()); + for (ClassTemplatePartialSpecializationDecl &P : PartialSpecs) + PS.push_back(P.getMostRecentDecl()); } ClassTemplatePartialSpecializationDecl * ClassTemplateDecl::findPartialSpecialization(QualType T) { ASTContext &Context = getASTContext(); - using llvm::FoldingSetVector; - typedef FoldingSetVector<ClassTemplatePartialSpecializationDecl>::iterator - partial_spec_iterator; - for (partial_spec_iterator P = getPartialSpecializations().begin(), - PEnd = getPartialSpecializations().end(); - P != PEnd; ++P) { - if (Context.hasSameType(P->getInjectedSpecializationType(), T)) - return P->getMostRecentDecl(); + for (ClassTemplatePartialSpecializationDecl &P : + getPartialSpecializations()) { + if (Context.hasSameType(P.getInjectedSpecializationType(), T)) + return P.getMostRecentDecl(); } return nullptr; @@ -447,12 +433,9 @@ ClassTemplatePartialSpecializationDecl * ClassTemplateDecl::findPartialSpecInstantiatedFromMember( ClassTemplatePartialSpecializationDecl *D) { Decl *DCanon = D->getCanonicalDecl(); - for (llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl>::iterator - P = getPartialSpecializations().begin(), - PEnd = getPartialSpecializations().end(); - P != PEnd; ++P) { - if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon) - return P->getMostRecentDecl(); + for (ClassTemplatePartialSpecializationDecl &P : getPartialSpecializations()) { + if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon) + return P.getMostRecentDecl(); } return nullptr; @@ -478,8 +461,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data()); CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(TemplateName(this), - &TemplateArgs[0], - TemplateArgs.size()); + TemplateArgs); return CommonPtr->InjectedClassNameType; } @@ -535,20 +517,14 @@ bool TemplateTypeParmDecl::isParameterPack() const { // NonTypeTemplateParmDecl Method Implementations //===----------------------------------------------------------------------===// -NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC, - SourceLocation StartLoc, - SourceLocation IdLoc, - unsigned D, unsigned P, - IdentifierInfo *Id, - QualType T, - TypeSourceInfo *TInfo, - const QualType *ExpandedTypes, - unsigned NumExpandedTypes, - TypeSourceInfo **ExpandedTInfos) - : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), - TemplateParmPosition(D, P), ParameterPack(true), - ExpandedParameterPack(true), NumExpandedTypes(NumExpandedTypes) { - if (ExpandedTypes && ExpandedTInfos) { +NonTypeTemplateParmDecl::NonTypeTemplateParmDecl( + DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D, + unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + ArrayRef<QualType> ExpandedTypes, ArrayRef<TypeSourceInfo *> ExpandedTInfos) + : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), + TemplateParmPosition(D, P), ParameterPack(true), + ExpandedParameterPack(true), NumExpandedTypes(ExpandedTypes.size()) { + if (!ExpandedTypes.empty() && !ExpandedTInfos.empty()) { auto TypesAndInfos = getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>(); for (unsigned I = 0; I != NumExpandedTypes; ++I) { @@ -568,20 +544,16 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, T, ParameterPack, TInfo); } -NonTypeTemplateParmDecl * -NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - unsigned D, unsigned P, - IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo, - const QualType *ExpandedTypes, - unsigned NumExpandedTypes, - TypeSourceInfo **ExpandedTInfos) { +NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create( + const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes, + ArrayRef<TypeSourceInfo *> ExpandedTInfos) { return new (C, DC, additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>( - NumExpandedTypes)) + ExpandedTypes.size())) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo, - ExpandedTypes, NumExpandedTypes, ExpandedTInfos); + ExpandedTypes, ExpandedTInfos); } NonTypeTemplateParmDecl * @@ -594,12 +566,14 @@ NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { NonTypeTemplateParmDecl * NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumExpandedTypes) { - return new (C, ID, - additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>( - NumExpandedTypes)) - NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(), 0, 0, - nullptr, QualType(), nullptr, nullptr, - NumExpandedTypes, nullptr); + auto *NTTP = + new (C, ID, additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>( + NumExpandedTypes)) + NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(), + 0, 0, nullptr, QualType(), nullptr, None, + None); + NTTP->NumExpandedTypes = NumExpandedTypes; + return NTTP; } SourceRange NonTypeTemplateParmDecl::getSourceRange() const { @@ -624,12 +598,12 @@ void TemplateTemplateParmDecl::anchor() { } TemplateTemplateParmDecl::TemplateTemplateParmDecl( DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, TemplateParameterList *Params, - unsigned NumExpansions, TemplateParameterList * const *Expansions) - : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), ParameterPack(true), - ExpandedParameterPack(true), NumExpandedParams(NumExpansions) { - if (Expansions) - std::uninitialized_copy(Expansions, Expansions + NumExpandedParams, + ArrayRef<TemplateParameterList *> Expansions) + : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), + TemplateParmPosition(D, P), ParameterPack(true), + ExpandedParameterPack(true), NumExpandedParams(Expansions.size()) { + if (!Expansions.empty()) + std::uninitialized_copy(Expansions.begin(), Expansions.end(), getTrailingObjects<TemplateParameterList *>()); } @@ -650,8 +624,7 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, ArrayRef<TemplateParameterList *> Expansions) { return new (C, DC, additionalSizeToAlloc<TemplateParameterList *>(Expansions.size())) - TemplateTemplateParmDecl(DC, L, D, P, Id, Params, Expansions.size(), - Expansions.data()); + TemplateTemplateParmDecl(DC, L, D, P, Id, Params, Expansions); } TemplateTemplateParmDecl * @@ -663,10 +636,12 @@ TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { TemplateTemplateParmDecl * TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumExpansions) { - return new (C, ID, - additionalSizeToAlloc<TemplateParameterList *>(NumExpansions)) - TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr, - nullptr, NumExpansions, nullptr); + auto *TTP = + new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions)) + TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr, + nullptr, None); + TTP->NumExpandedParams = NumExpansions; + return TTP; } SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const { @@ -685,19 +660,18 @@ void TemplateTemplateParmDecl::setDefaultArgument( //===----------------------------------------------------------------------===// // TemplateArgumentList Implementation //===----------------------------------------------------------------------===// -TemplateArgumentList::TemplateArgumentList(const TemplateArgument *Args, - unsigned NumArgs) - : Arguments(getTrailingObjects<TemplateArgument>()), NumArguments(NumArgs) { - std::uninitialized_copy(Args, Args + NumArgs, +TemplateArgumentList::TemplateArgumentList(ArrayRef<TemplateArgument> Args) + : Arguments(getTrailingObjects<TemplateArgument>()), + NumArguments(Args.size()) { + std::uninitialized_copy(Args.begin(), Args.end(), getTrailingObjects<TemplateArgument>()); } TemplateArgumentList * TemplateArgumentList::CreateCopy(ASTContext &Context, - const TemplateArgument *Args, - unsigned NumArgs) { - void *Mem = Context.Allocate(totalSizeToAlloc<TemplateArgument>(NumArgs)); - return new (Mem) TemplateArgumentList(Args, NumArgs); + ArrayRef<TemplateArgument> Args) { + void *Mem = Context.Allocate(totalSizeToAlloc<TemplateArgument>(Args.size())); + return new (Mem) TemplateArgumentList(Args); } FunctionTemplateSpecializationInfo * @@ -732,15 +706,14 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef<TemplateArgument> Args, ClassTemplateSpecializationDecl *PrevDecl) : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc, SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), ExplicitInfo(nullptr), - TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)), + TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)), SpecializationKind(TSK_Undeclared) { } @@ -756,13 +729,12 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, SourceLocation StartLoc, SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef<TemplateArgument> Args, ClassTemplateSpecializationDecl *PrevDecl) { ClassTemplateSpecializationDecl *Result = new (Context, DC) ClassTemplateSpecializationDecl( Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc, - SpecializedTemplate, Args, NumArgs, PrevDecl); + SpecializedTemplate, Args, PrevDecl); Result->MayHaveOutOfDateDef = false; Context.getTypeDeclType(Result, PrevDecl); @@ -784,7 +756,7 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic( const TemplateArgumentList &TemplateArgs = getTemplateArgs(); TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.data(), TemplateArgs.size(), Policy); + OS, TemplateArgs.asArray(), Policy); } ClassTemplateDecl * @@ -806,7 +778,7 @@ ClassTemplateSpecializationDecl::getSourceRange() const { getSpecializationKind() == TSK_ExplicitInstantiationDefinition); if (getExternLoc().isValid()) Begin = getExternLoc(); - SourceLocation End = getRBraceLoc(); + SourceLocation End = getBraceRange().getEnd(); if (End.isInvalid()) End = getTypeAsWritten()->getTypeLoc().getEndLoc(); return SourceRange(Begin, End); @@ -846,15 +818,14 @@ ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef<TemplateArgument> Args, const ASTTemplateArgumentListInfo *ArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl) : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc, SpecializedTemplate, - Args, NumArgs, PrevDecl), + Args, PrevDecl), TemplateParams(Params), ArgsAsWritten(ArgInfos), InstantiatedFromMember(nullptr, false) { @@ -867,8 +838,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef<TemplateArgument> Args, const TemplateArgumentListInfo &ArgInfos, QualType CanonInjectedType, ClassTemplatePartialSpecializationDecl *PrevDecl) { @@ -878,7 +848,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, ClassTemplatePartialSpecializationDecl *Result = new (Context, DC) ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc, Params, SpecializedTemplate, Args, - NumArgs, ASTArgInfos, PrevDecl); + ASTArgInfos, PrevDecl); Result->setSpecializationKind(TSK_ExplicitSpecialization); Result->MayHaveOutOfDateDef = false; @@ -901,15 +871,12 @@ ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, void FriendTemplateDecl::anchor() { } -FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context, - DeclContext *DC, - SourceLocation L, - unsigned NParams, - TemplateParameterList **Params, - FriendUnion Friend, - SourceLocation FLoc) { - return new (Context, DC) FriendTemplateDecl(DC, L, NParams, Params, - Friend, FLoc); +FriendTemplateDecl * +FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC, + SourceLocation L, + MutableArrayRef<TemplateParameterList *> Params, + FriendUnion Friend, SourceLocation FLoc) { + return new (Context, DC) FriendTemplateDecl(DC, L, Params, Friend, FLoc); } FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C, @@ -1065,23 +1032,17 @@ void VarTemplateDecl::getPartialSpecializations( getPartialSpecializations(); PS.clear(); PS.reserve(PartialSpecs.size()); - for (llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>::iterator - P = PartialSpecs.begin(), - PEnd = PartialSpecs.end(); - P != PEnd; ++P) - PS.push_back(P->getMostRecentDecl()); + for (VarTemplatePartialSpecializationDecl &P : PartialSpecs) + PS.push_back(P.getMostRecentDecl()); } VarTemplatePartialSpecializationDecl * VarTemplateDecl::findPartialSpecInstantiatedFromMember( VarTemplatePartialSpecializationDecl *D) { Decl *DCanon = D->getCanonicalDecl(); - for (llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>::iterator - P = getPartialSpecializations().begin(), - PEnd = getPartialSpecializations().end(); - P != PEnd; ++P) { - if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon) - return P->getMostRecentDecl(); + for (VarTemplatePartialSpecializationDecl &P : getPartialSpecializations()) { + if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon) + return P.getMostRecentDecl(); } return nullptr; @@ -1093,12 +1054,11 @@ VarTemplateDecl::findPartialSpecInstantiatedFromMember( VarTemplateSpecializationDecl::VarTemplateSpecializationDecl( Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, - TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, - unsigned NumArgs) + TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args) : VarDecl(DK, Context, DC, StartLoc, IdLoc, SpecializedTemplate->getIdentifier(), T, TInfo, S), SpecializedTemplate(SpecializedTemplate), ExplicitInfo(nullptr), - TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)), + TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)), SpecializationKind(TSK_Undeclared) {} VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK, @@ -1110,11 +1070,10 @@ VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK, VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, - TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, - unsigned NumArgs) { + TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args) { return new (Context, DC) VarTemplateSpecializationDecl( VarTemplateSpecialization, Context, DC, StartLoc, IdLoc, - SpecializedTemplate, T, TInfo, S, Args, NumArgs); + SpecializedTemplate, T, TInfo, S, Args); } VarTemplateSpecializationDecl * @@ -1129,7 +1088,7 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic( const TemplateArgumentList &TemplateArgs = getTemplateArgs(); TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.data(), TemplateArgs.size(), Policy); + OS, TemplateArgs.asArray(), Policy); } VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const { @@ -1141,11 +1100,10 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const { void VarTemplateSpecializationDecl::setTemplateArgsInfo( const TemplateArgumentListInfo &ArgsInfo) { - unsigned N = ArgsInfo.size(); TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc()); TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc()); - for (unsigned I = 0; I != N; ++I) - TemplateArgsInfo.addArgument(ArgsInfo[I]); + for (const TemplateArgumentLoc &Loc : ArgsInfo.arguments()) + TemplateArgsInfo.addArgument(Loc); } //===----------------------------------------------------------------------===// @@ -1157,11 +1115,11 @@ VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, const TemplateArgument *Args, unsigned NumArgs, + StorageClass S, ArrayRef<TemplateArgument> Args, const ASTTemplateArgumentListInfo *ArgInfos) : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context, DC, StartLoc, IdLoc, SpecializedTemplate, T, - TInfo, S, Args, NumArgs), + TInfo, S, Args), TemplateParams(Params), ArgsAsWritten(ArgInfos), InstantiatedFromMember(nullptr, false) { // TODO: The template parameters should be in DC by now. Verify. @@ -1173,7 +1131,7 @@ VarTemplatePartialSpecializationDecl::Create( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, const TemplateArgument *Args, unsigned NumArgs, + StorageClass S, ArrayRef<TemplateArgument> Args, const TemplateArgumentListInfo &ArgInfos) { const ASTTemplateArgumentListInfo *ASTArgInfos = ASTTemplateArgumentListInfo::Create(Context, ArgInfos); @@ -1181,7 +1139,7 @@ VarTemplatePartialSpecializationDecl::Create( VarTemplatePartialSpecializationDecl *Result = new (Context, DC) VarTemplatePartialSpecializationDecl( Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, - S, Args, NumArgs, ASTArgInfos); + S, Args, ASTArgInfos); Result->setSpecializationKind(TSK_ExplicitSpecialization); return Result; } @@ -1239,11 +1197,34 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { Params, SourceLocation()); } +static TemplateParameterList * +createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) { + // std::size_t Index + TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(C.getSizeType()); + auto *Index = NonTypeTemplateParmDecl::Create( + C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/0, + /*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo); + + // typename ...T + auto *Ts = TemplateTypeParmDecl::Create( + C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true); + Ts->setImplicit(true); + + // template <std::size_t Index, typename ...T> + NamedDecl *Params[] = {Index, Ts}; + return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), + llvm::makeArrayRef(Params), + SourceLocation()); +} + static TemplateParameterList *createBuiltinTemplateParameterList( const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) { switch (BTK) { case BTK__make_integer_seq: return createMakeIntegerSeqParameterList(C, DC); + case BTK__type_pack_element: + return createTypePackElementParameterList(C, DC); } llvm_unreachable("unhandled BuiltinTemplateKind!"); diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index b2f27275f49c..2a988e1d22d0 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" @@ -133,36 +133,45 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { llvm_unreachable("Invalid DeclarationName Kind!"); } -raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { +static void printCXXConstructorDestructorName(QualType ClassType, + raw_ostream &OS, + PrintingPolicy Policy) { + // We know we're printing C++ here. Ensure we print types properly. + Policy.adjustForCPlusPlus(); + + if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) { + OS << *ClassRec->getDecl(); + return; + } + if (Policy.SuppressTemplateArgsInCXXConstructors) { + if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) { + OS << *InjTy->getDecl(); + return; + } + } + ClassType.print(OS, Policy); +} + +void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { + DeclarationName &N = *this; switch (N.getNameKind()) { case DeclarationName::Identifier: if (const IdentifierInfo *II = N.getAsIdentifierInfo()) OS << II->getName(); - return OS; + return; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: N.getObjCSelector().print(OS); - return OS; - - case DeclarationName::CXXConstructorName: { - QualType ClassType = N.getCXXNameType(); - if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) - return OS << *ClassRec->getDecl(); - LangOptions LO; - LO.CPlusPlus = true; - return OS << ClassType.getAsString(PrintingPolicy(LO)); - } + return; + + case DeclarationName::CXXConstructorName: + return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); case DeclarationName::CXXDestructorName: { OS << '~'; - QualType Type = N.getCXXNameType(); - if (const RecordType *Rec = Type->getAs<RecordType>()) - return OS << *Rec->getDecl(); - LangOptions LO; - LO.CPlusPlus = true; - return OS << Type.getAsString(PrintingPolicy(LO)); + return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); } case DeclarationName::CXXOperatorName: { @@ -178,29 +187,41 @@ raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { OS << "operator"; if (OpName[0] >= 'a' && OpName[0] <= 'z') OS << ' '; - return OS << OpName; + OS << OpName; + return; } case DeclarationName::CXXLiteralOperatorName: - return OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName(); + OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName(); + return; case DeclarationName::CXXConversionFunctionName: { OS << "operator "; QualType Type = N.getCXXNameType(); - if (const RecordType *Rec = Type->getAs<RecordType>()) - return OS << *Rec->getDecl(); - LangOptions LO; - LO.CPlusPlus = true; - LO.Bool = true; - return OS << Type.getAsString(PrintingPolicy(LO)); + if (const RecordType *Rec = Type->getAs<RecordType>()) { + OS << *Rec->getDecl(); + return; + } + // We know we're printing C++ here, ensure we print 'bool' properly. + PrintingPolicy CXXPolicy = Policy; + CXXPolicy.adjustForCPlusPlus(); + Type.print(OS, CXXPolicy); + return; } case DeclarationName::CXXUsingDirective: - return OS << "<using-directive>"; + OS << "<using-directive>"; + return; } llvm_unreachable("Unexpected declaration name kind"); } +raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) { + LangOptions LO; + N.print(OS, PrintingPolicy(LO)); + return OS; +} + } // end namespace clang DeclarationName::NameKind DeclarationName::getNameKind() const { @@ -333,7 +354,7 @@ DeclarationName DeclarationName::getUsingDirectiveName() { return DeclarationName(Ptr); } -void DeclarationName::dump() const { +LLVM_DUMP_METHOD void DeclarationName::dump() const { llvm::errs() << *this << '\n'; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 52f34df43565..091e8787d8b6 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -985,7 +985,7 @@ void StringLiteral::setString(const ASTContext &C, StringRef Str, break; } default: - assert(false && "unsupported CharByteWidth"); + llvm_unreachable("unsupported CharByteWidth"); } } @@ -1084,20 +1084,8 @@ StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM, /// corresponds to, e.g. "sizeof" or "[pre]++". StringRef UnaryOperator::getOpcodeStr(Opcode Op) { switch (Op) { - case UO_PostInc: return "++"; - case UO_PostDec: return "--"; - case UO_PreInc: return "++"; - case UO_PreDec: return "--"; - case UO_AddrOf: return "&"; - case UO_Deref: return "*"; - case UO_Plus: return "+"; - case UO_Minus: return "-"; - case UO_Not: return "~"; - case UO_LNot: return "!"; - case UO_Real: return "__real"; - case UO_Imag: return "__imag"; - case UO_Extension: return "__extension__"; - case UO_Coawait: return "co_await"; +#define UNARY_OPERATION(Name, Spelling) case UO_##Name: return Spelling; +#include "clang/AST/OperationKinds.def" } llvm_unreachable("Unknown unary operator"); } @@ -1138,28 +1126,23 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) { // Postfix Operators. //===----------------------------------------------------------------------===// -CallExpr::CallExpr(const ASTContext& C, StmtClass SC, Expr *fn, - unsigned NumPreArgs, ArrayRef<Expr*> args, QualType t, +CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, + ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t, ExprValueKind VK, SourceLocation rparenloc) - : Expr(SC, t, VK, OK_Ordinary, - fn->isTypeDependent(), - fn->isValueDependent(), - fn->isInstantiationDependent(), - fn->containsUnexpandedParameterPack()), - NumArgs(args.size()) { - - SubExprs = new (C) Stmt*[args.size()+PREARGS_START+NumPreArgs]; + : Expr(SC, t, VK, OK_Ordinary, fn->isTypeDependent(), + fn->isValueDependent(), fn->isInstantiationDependent(), + fn->containsUnexpandedParameterPack()), + NumArgs(args.size()) { + + unsigned NumPreArgs = preargs.size(); + SubExprs = new (C) Stmt *[args.size()+PREARGS_START+NumPreArgs]; SubExprs[FN] = fn; + for (unsigned i = 0; i != NumPreArgs; ++i) { + updateDependenciesFromArg(preargs[i]); + SubExprs[i+PREARGS_START] = preargs[i]; + } 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; - + updateDependenciesFromArg(args[i]); SubExprs[i+PREARGS_START+NumPreArgs] = args[i]; } @@ -1167,9 +1150,14 @@ CallExpr::CallExpr(const ASTContext& C, StmtClass SC, Expr *fn, RParenLoc = rparenloc; } +CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, + ArrayRef<Expr *> args, QualType t, ExprValueKind VK, + SourceLocation rparenloc) + : CallExpr(C, SC, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc) {} + CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args, QualType t, ExprValueKind VK, SourceLocation rparenloc) - : CallExpr(C, CallExprClass, fn, /*NumPreArgs=*/0, args, t, VK, rparenloc) { + : CallExpr(C, CallExprClass, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc) { } CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty) @@ -1179,10 +1167,21 @@ CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty) : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) { // FIXME: Why do we allocate this? - SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs]; + SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs](); CallExprBits.NumPreArgs = NumPreArgs; } +void CallExpr::updateDependenciesFromArg(Expr *Arg) { + if (Arg->isTypeDependent()) + ExprBits.TypeDependent = true; + if (Arg->isValueDependent()) + ExprBits.ValueDependent = true; + if (Arg->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (Arg->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; +} + Decl *CallExpr::getCalleeDecl() { Expr *CEE = getCallee()->IgnoreParenImpCasts(); @@ -1597,120 +1596,9 @@ bool CastExpr::CastConsistency() const { const char *CastExpr::getCastKindName() const { switch (getCastKind()) { - case CK_Dependent: - return "Dependent"; - case CK_BitCast: - return "BitCast"; - case CK_LValueBitCast: - return "LValueBitCast"; - case CK_LValueToRValue: - return "LValueToRValue"; - case CK_NoOp: - return "NoOp"; - case CK_BaseToDerived: - return "BaseToDerived"; - case CK_DerivedToBase: - return "DerivedToBase"; - case CK_UncheckedDerivedToBase: - return "UncheckedDerivedToBase"; - case CK_Dynamic: - return "Dynamic"; - case CK_ToUnion: - return "ToUnion"; - case CK_ArrayToPointerDecay: - return "ArrayToPointerDecay"; - case CK_FunctionToPointerDecay: - return "FunctionToPointerDecay"; - case CK_NullToMemberPointer: - return "NullToMemberPointer"; - case CK_NullToPointer: - return "NullToPointer"; - case CK_BaseToDerivedMemberPointer: - return "BaseToDerivedMemberPointer"; - case CK_DerivedToBaseMemberPointer: - return "DerivedToBaseMemberPointer"; - case CK_ReinterpretMemberPointer: - return "ReinterpretMemberPointer"; - case CK_UserDefinedConversion: - return "UserDefinedConversion"; - case CK_ConstructorConversion: - return "ConstructorConversion"; - case CK_IntegralToPointer: - return "IntegralToPointer"; - case CK_PointerToIntegral: - return "PointerToIntegral"; - case CK_PointerToBoolean: - return "PointerToBoolean"; - case CK_ToVoid: - return "ToVoid"; - case CK_VectorSplat: - return "VectorSplat"; - case CK_IntegralCast: - return "IntegralCast"; - case CK_BooleanToSignedIntegral: - return "BooleanToSignedIntegral"; - case CK_IntegralToBoolean: - return "IntegralToBoolean"; - case CK_IntegralToFloating: - return "IntegralToFloating"; - case CK_FloatingToIntegral: - return "FloatingToIntegral"; - case CK_FloatingCast: - return "FloatingCast"; - case CK_FloatingToBoolean: - return "FloatingToBoolean"; - case CK_MemberPointerToBoolean: - return "MemberPointerToBoolean"; - case CK_CPointerToObjCPointerCast: - return "CPointerToObjCPointerCast"; - case CK_BlockPointerToObjCPointerCast: - return "BlockPointerToObjCPointerCast"; - case CK_AnyPointerToBlockPointerCast: - return "AnyPointerToBlockPointerCast"; - case CK_ObjCObjectLValueCast: - return "ObjCObjectLValueCast"; - case CK_FloatingRealToComplex: - return "FloatingRealToComplex"; - case CK_FloatingComplexToReal: - return "FloatingComplexToReal"; - case CK_FloatingComplexToBoolean: - return "FloatingComplexToBoolean"; - case CK_FloatingComplexCast: - return "FloatingComplexCast"; - case CK_FloatingComplexToIntegralComplex: - return "FloatingComplexToIntegralComplex"; - case CK_IntegralRealToComplex: - return "IntegralRealToComplex"; - case CK_IntegralComplexToReal: - return "IntegralComplexToReal"; - case CK_IntegralComplexToBoolean: - return "IntegralComplexToBoolean"; - case CK_IntegralComplexCast: - return "IntegralComplexCast"; - case CK_IntegralComplexToFloatingComplex: - return "IntegralComplexToFloatingComplex"; - case CK_ARCConsumeObject: - return "ARCConsumeObject"; - case CK_ARCProduceObject: - return "ARCProduceObject"; - case CK_ARCReclaimReturnedObject: - return "ARCReclaimReturnedObject"; - case CK_ARCExtendBlockObject: - return "ARCExtendBlockObject"; - case CK_AtomicToNonAtomic: - return "AtomicToNonAtomic"; - case CK_NonAtomicToAtomic: - return "NonAtomicToAtomic"; - case CK_CopyAndAutoreleaseBlockObject: - return "CopyAndAutoreleaseBlockObject"; - case CK_BuiltinFnToFnPtr: - return "BuiltinFnToFnPtr"; - case CK_ZeroToOCLEvent: - return "ZeroToOCLEvent"; - case CK_AddressSpaceConversion: - return "AddressSpaceConversion"; +#define CAST_OPERATION(Name) case CK_##Name: return #Name; +#include "clang/AST/OperationKinds.def" } - llvm_unreachable("Unhandled cast kind!"); } @@ -1733,8 +1621,13 @@ Expr *CastExpr::getSubExprAsWritten() { // subexpression describing the call; strip it off. if (E->getCastKind() == CK_ConstructorConversion) SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0); - else if (E->getCastKind() == CK_UserDefinedConversion) - SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument(); + else if (E->getCastKind() == CK_UserDefinedConversion) { + assert((isa<CXXMemberCallExpr>(SubExpr) || + isa<BlockExpr>(SubExpr)) && + "Unexpected SubExpr for CK_UserDefinedConversion."); + if (isa<CXXMemberCallExpr>(SubExpr)) + SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument(); + } // If the subexpression we're left with is an implicit cast, look // through that, too. @@ -1802,40 +1695,9 @@ CStyleCastExpr *CStyleCastExpr::CreateEmpty(const ASTContext &C, /// corresponds to, e.g. "<<=". StringRef BinaryOperator::getOpcodeStr(Opcode Op) { switch (Op) { - case BO_PtrMemD: return ".*"; - case BO_PtrMemI: return "->*"; - case BO_Mul: return "*"; - case BO_Div: return "/"; - case BO_Rem: return "%"; - case BO_Add: return "+"; - case BO_Sub: return "-"; - case BO_Shl: return "<<"; - case BO_Shr: return ">>"; - case BO_LT: return "<"; - case BO_GT: return ">"; - case BO_LE: return "<="; - case BO_GE: return ">="; - case BO_EQ: return "=="; - case BO_NE: return "!="; - case BO_And: return "&"; - case BO_Xor: return "^"; - case BO_Or: return "|"; - case BO_LAnd: return "&&"; - case BO_LOr: return "||"; - case BO_Assign: return "="; - case BO_MulAssign: return "*="; - case BO_DivAssign: return "/="; - case BO_RemAssign: return "%="; - case BO_AddAssign: return "+="; - case BO_SubAssign: return "-="; - case BO_ShlAssign: return "<<="; - case BO_ShrAssign: return ">>="; - case BO_AndAssign: return "&="; - case BO_XorAssign: return "^="; - case BO_OrAssign: return "|="; - case BO_Comma: return ","; +#define BINARY_OPERATION(Name, Spelling) case BO_##Name: return Spelling; +#include "clang/AST/OperationKinds.def" } - llvm_unreachable("Invalid OpCode!"); } @@ -2994,6 +2856,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case ObjCStringLiteralClass: case ObjCEncodeExprClass: case ObjCBoolLiteralExprClass: + case ObjCAvailabilityCheckExprClass: case CXXUuidofExprClass: case OpaqueValueExprClass: // These never have a side-effect. @@ -3028,7 +2891,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case CXXThrowExprClass: case CXXNewExprClass: case CXXDeleteExprClass: - case ExprWithCleanupsClass: case CoawaitExprClass: case CoyieldExprClass: // These always have a side-effect. @@ -3041,6 +2903,12 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, return Finder.hasSideEffects(); } + case ExprWithCleanupsClass: + if (IncludePossibleEffects) + if (cast<ExprWithCleanups>(this)->cleanupsHaveSideEffects()) + return true; + break; + case ParenExprClass: case ArraySubscriptExprClass: case OMPArraySectionExprClass: @@ -3141,6 +3009,13 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, break; } + case CXXInheritedCtorInitExprClass: { + const auto *ICIE = cast<CXXInheritedCtorInitExpr>(this); + if (!ICIE->getConstructor()->isTrivial() && IncludePossibleEffects) + return true; + break; + } + case LambdaExprClass: { const LambdaExpr *LE = cast<LambdaExpr>(this); for (LambdaExpr::capture_iterator I = LE->capture_begin(), @@ -3643,8 +3518,7 @@ IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() const { } DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, - unsigned NumDesignators, - const Designator *Designators, + llvm::ArrayRef<Designator> Designators, SourceLocation EqualOrColonLoc, bool GNUSyntax, ArrayRef<Expr*> IndexExprs, @@ -3655,7 +3529,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, Init->isInstantiationDependent(), Init->containsUnexpandedParameterPack()), EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax), - NumDesignators(NumDesignators), NumSubExprs(IndexExprs.size() + 1) { + NumDesignators(Designators.size()), NumSubExprs(IndexExprs.size() + 1) { this->Designators = new (C) Designator[NumDesignators]; // Record the initializer itself. @@ -3709,14 +3583,14 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty, } DesignatedInitExpr * -DesignatedInitExpr::Create(const ASTContext &C, Designator *Designators, - unsigned NumDesignators, +DesignatedInitExpr::Create(const ASTContext &C, + llvm::ArrayRef<Designator> Designators, ArrayRef<Expr*> IndexExprs, SourceLocation ColonOrEqualLoc, bool UsesColonSyntax, Expr *Init) { void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(IndexExprs.size() + 1), llvm::alignOf<DesignatedInitExpr>()); - return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators, + return new (Mem) DesignatedInitExpr(C, C.VoidTy, Designators, ColonOrEqualLoc, UsesColonSyntax, IndexExprs, Init); } @@ -3747,8 +3621,8 @@ SourceRange DesignatedInitExpr::getDesignatorsSourceRange() const { SourceLocation DesignatedInitExpr::getLocStart() const { SourceLocation StartLoc; - Designator &First = - *const_cast<DesignatedInitExpr*>(this)->designators_begin(); + auto *DIE = const_cast<DesignatedInitExpr *>(this); + Designator &First = *DIE->getDesignator(0); if (First.isFieldDesignator()) { if (GNUSyntax) StartLoc = SourceLocation::getFromRawEncoding(First.Field.FieldLoc); @@ -4010,16 +3884,18 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { llvm_unreachable("unknown atomic op"); } -QualType OMPArraySectionExpr::getBaseOriginalType(Expr *Base) { +QualType OMPArraySectionExpr::getBaseOriginalType(const 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())) { + while (auto *ASE = + dyn_cast<ArraySubscriptExpr>(Base->IgnoreParenImpCasts())) { Base = ASE->getBase(); ++ArraySectionCount; } + Base = Base->IgnoreParenImpCasts(); auto OriginalTy = Base->getType(); if (auto *DRE = dyn_cast<DeclRefExpr>(Base)) if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index ea983340a293..a13033d47467 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -54,79 +54,6 @@ QualType CXXUuidofExpr::getTypeOperand(ASTContext &Context) const { Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType(), Quals); } -// static -const UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT, - bool *RDHasMultipleGUIDsPtr) { - // Optionally remove one level of pointer, reference or array indirection. - const Type *Ty = QT.getTypePtr(); - if (QT->isPointerType() || QT->isReferenceType()) - Ty = QT->getPointeeType().getTypePtr(); - else if (QT->isArrayType()) - Ty = Ty->getBaseElementTypeUnsafe(); - - const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - if (!RD) - return nullptr; - - if (const UuidAttr *Uuid = RD->getMostRecentDecl()->getAttr<UuidAttr>()) - return Uuid; - - // __uuidof can grab UUIDs from template arguments. - if (const ClassTemplateSpecializationDecl *CTSD = - dyn_cast<ClassTemplateSpecializationDecl>(RD)) { - const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); - const UuidAttr *UuidForRD = nullptr; - - for (const TemplateArgument &TA : TAL.asArray()) { - bool SeenMultipleGUIDs = false; - - const UuidAttr *UuidForTA = nullptr; - if (TA.getKind() == TemplateArgument::Type) - UuidForTA = GetUuidAttrOfType(TA.getAsType(), &SeenMultipleGUIDs); - else if (TA.getKind() == TemplateArgument::Declaration) - UuidForTA = - GetUuidAttrOfType(TA.getAsDecl()->getType(), &SeenMultipleGUIDs); - - // If the template argument has a UUID, there are three cases: - // - This is the first UUID seen for this RecordDecl. - // - This is a different UUID than previously seen for this RecordDecl. - // - This is the same UUID than previously seen for this RecordDecl. - if (UuidForTA) { - if (!UuidForRD) - UuidForRD = UuidForTA; - else if (UuidForRD != UuidForTA) - SeenMultipleGUIDs = true; - } - - // Seeing multiple UUIDs means that we couldn't find a UUID - if (SeenMultipleGUIDs) { - if (RDHasMultipleGUIDsPtr) - *RDHasMultipleGUIDsPtr = true; - return nullptr; - } - } - - return UuidForRD; - } - - return nullptr; -} - -StringRef CXXUuidofExpr::getUuidAsStringRef(ASTContext &Context) const { - StringRef Uuid; - if (isTypeOperand()) - Uuid = CXXUuidofExpr::GetUuidAttrOfType(getTypeOperand(Context))->getGuid(); - else { - // Special case: __uuidof(0) means an all-zero GUID. - Expr *Op = getExprOperand(); - if (!Op->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) - Uuid = CXXUuidofExpr::GetUuidAttrOfType(Op->getType())->getGuid(); - else - Uuid = "00000000-0000-0000-0000-000000000000"; - } - return Uuid; -} - // CXXScalarValueInitExpr SourceLocation CXXScalarValueInitExpr::getLocStart() const { return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : RParenLoc; @@ -823,7 +750,8 @@ SourceLocation CXXTemporaryObjectExpr::getLocEnd() const { CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T, SourceLocation Loc, - CXXConstructorDecl *D, bool Elidable, + CXXConstructorDecl *Ctor, + bool Elidable, ArrayRef<Expr*> Args, bool HadMultipleCandidates, bool ListInitialization, @@ -831,8 +759,8 @@ CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange) { - return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, - Elidable, Args, + return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, + Ctor, Elidable, Args, HadMultipleCandidates, ListInitialization, StdInitListInitialization, ZeroInitialization, ConstructKind, @@ -841,8 +769,9 @@ CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T, CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T, SourceLocation Loc, - CXXConstructorDecl *D, bool elidable, - ArrayRef<Expr*> args, + CXXConstructorDecl *Ctor, + bool Elidable, + ArrayRef<Expr*> Args, bool HadMultipleCandidates, bool ListInitialization, bool StdInitListInitialization, @@ -853,28 +782,28 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, T->isDependentType(), T->isDependentType(), T->isInstantiationDependentType(), T->containsUnexpandedParameterPack()), - Constructor(D), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange), - NumArgs(args.size()), - Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates), + Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange), + NumArgs(Args.size()), + Elidable(Elidable), HadMultipleCandidates(HadMultipleCandidates), ListInitialization(ListInitialization), StdInitListInitialization(StdInitListInitialization), ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), Args(nullptr) { if (NumArgs) { - Args = new (C) Stmt*[args.size()]; + this->Args = new (C) Stmt*[Args.size()]; - for (unsigned i = 0; i != args.size(); ++i) { - assert(args[i] && "NULL argument in CXXConstructExpr"); + for (unsigned i = 0; i != Args.size(); ++i) { + assert(Args[i] && "NULL argument in CXXConstructExpr"); - if (args[i]->isValueDependent()) + if (Args[i]->isValueDependent()) ExprBits.ValueDependent = true; - if (args[i]->isInstantiationDependent()) + if (Args[i]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (args[i]->containsUnexpandedParameterPack()) + if (Args[i]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - Args[i] = args[i]; + this->Args[i] = Args[i]; } } } @@ -889,8 +818,12 @@ LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit, Bits |= Capture_Implicit; switch (Kind) { + case LCK_StarThis: + Bits |= Capture_ByCopy; + // Fall through case LCK_This: assert(!Var && "'this' capture cannot have a variable!"); + Bits |= Capture_This; break; case LCK_ByCopy: @@ -901,18 +834,17 @@ LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit, break; case LCK_VLAType: assert(!Var && "VLA type capture cannot have a variable!"); - Bits |= Capture_ByCopy; break; } DeclAndBits.setInt(Bits); } LambdaCaptureKind LambdaCapture::getCaptureKind() const { - Decl *D = DeclAndBits.getPointer(); + if (capturesVLAType()) + return LCK_VLAType; bool CapByCopy = DeclAndBits.getInt() & Capture_ByCopy; - if (!D) - return CapByCopy ? LCK_VLAType : LCK_This; - + if (capturesThis()) + return CapByCopy ? LCK_StarThis : LCK_This; return CapByCopy ? LCK_ByCopy : LCK_ByRef; } @@ -1091,6 +1023,7 @@ bool LambdaExpr::isMutable() const { } ExprWithCleanups::ExprWithCleanups(Expr *subexpr, + bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects) : Expr(ExprWithCleanupsClass, subexpr->getType(), subexpr->getValueKind(), subexpr->getObjectKind(), @@ -1098,16 +1031,19 @@ ExprWithCleanups::ExprWithCleanups(Expr *subexpr, subexpr->isInstantiationDependent(), subexpr->containsUnexpandedParameterPack()), SubExpr(subexpr) { + ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects; ExprWithCleanupsBits.NumObjects = objects.size(); for (unsigned i = 0, e = objects.size(); i != e; ++i) getTrailingObjects<CleanupObject>()[i] = objects[i]; } ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr, + bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects) { void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()), llvm::alignOf<ExprWithCleanups>()); - return new (buffer) ExprWithCleanups(subexpr, objects); + return new (buffer) + ExprWithCleanups(subexpr, CleanupsHaveSideEffects, objects); } ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects) diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index a47b03c0afba..89cc9bc18ef0 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -178,6 +178,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ObjCArrayLiteralClass: case Expr::ObjCDictionaryLiteralClass: case Expr::ObjCBoolLiteralExprClass: + case Expr::ObjCAvailabilityCheckExprClass: case Expr::ParenListExprClass: case Expr::SizeOfPackExprClass: case Expr::SubstNonTypeTemplateParmPackExprClass: @@ -360,6 +361,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // Some C++ expressions are always class temporaries. case Expr::CXXConstructExprClass: + case Expr::CXXInheritedCtorInitExprClass: case Expr::CXXTemporaryObjectExprClass: case Expr::LambdaExprClass: case Expr::CXXStdInitializerListExprClass: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index fa652ba1b0ab..a25a6c7e5135 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -36,6 +36,7 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" @@ -157,13 +158,13 @@ namespace { /// True if the subobject was named in a manner not supported by C++11. Such /// lvalues can still be folded, but they are not core constant expressions /// and we cannot perform lvalue-to-rvalue conversions on them. - bool Invalid : 1; + unsigned Invalid : 1; /// Is this a pointer one past the end of an object? - bool IsOnePastTheEnd : 1; + unsigned IsOnePastTheEnd : 1; /// Indicator of whether the most-derived object is an array element. - bool MostDerivedIsArrayElement : 1; + unsigned MostDerivedIsArrayElement : 1; /// The length of the path to the most-derived object of which this is a /// subobject. @@ -477,6 +478,9 @@ namespace { /// fold (not just why it's not strictly a constant expression)? bool HasFoldFailureDiagnostic; + /// \brief Whether or not we're currently speculatively evaluating. + bool IsSpeculativelyEvaluating; + enum EvaluationMode { /// Evaluate as a constant expression. Stop if we find that the expression /// is not a constant expression. @@ -541,7 +545,8 @@ namespace { BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr), EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), - HasFoldFailureDiagnostic(false), EvalMode(Mode) {} + HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false), + EvalMode(Mode) {} void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; @@ -557,12 +562,12 @@ namespace { return false; if (NextCallIndex == 0) { // NextCallIndex has wrapped around. - Diag(Loc, diag::note_constexpr_call_limit_exceeded); + FFDiag(Loc, diag::note_constexpr_call_limit_exceeded); return false; } if (CallStackDepth <= getLangOpts().ConstexprCallDepth) return true; - Diag(Loc, diag::note_constexpr_depth_limit_exceeded) + FFDiag(Loc, diag::note_constexpr_depth_limit_exceeded) << getLangOpts().ConstexprCallDepth; return false; } @@ -579,7 +584,7 @@ namespace { bool nextStep(const Stmt *S) { if (!StepsLeft) { - Diag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded); + FFDiag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded); return false; } --StepsLeft; @@ -597,11 +602,10 @@ namespace { /// Add notes containing a call stack to the current point of evaluation. void addCallStack(unsigned Limit); - public: - /// Diagnose that the evaluation cannot be folded. - OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId - = diag::note_invalid_subexpr_in_const_expr, - unsigned ExtraNotes = 0, bool IsCCEDiag = false) { + private: + OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId, + unsigned ExtraNotes, bool IsCCEDiag) { + 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, @@ -646,12 +650,20 @@ namespace { HasActiveDiagnostic = false; return OptionalDiagnostic(); } - - OptionalDiagnostic Diag(const Expr *E, diag::kind DiagId + public: + // Diagnose that the evaluation could not be folded (FF => FoldFailure) + OptionalDiagnostic + FFDiag(SourceLocation Loc, + diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, + unsigned ExtraNotes = 0) { + return Diag(Loc, DiagId, ExtraNotes, false); + } + + OptionalDiagnostic FFDiag(const Expr *E, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, - unsigned ExtraNotes = 0, bool IsCCEDiag = false) { + unsigned ExtraNotes = 0) { if (EvalStatus.Diag) - return Diag(E->getExprLoc(), DiagId, ExtraNotes, IsCCEDiag); + return Diag(E->getExprLoc(), DiagId, ExtraNotes, /*IsCCEDiag*/false); HasActiveDiagnostic = false; return OptionalDiagnostic(); } @@ -661,8 +673,7 @@ namespace { /// /// FIXME: Stop evaluating if we're in EM_ConstantExpression or /// EM_PotentialConstantExpression mode and we produce one of these. - template<typename LocArg> - OptionalDiagnostic CCEDiag(LocArg Loc, diag::kind DiagId + OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { // Don't override a previous diagnostic. Don't bother collecting @@ -673,7 +684,11 @@ namespace { } return Diag(Loc, DiagId, ExtraNotes, true); } - + OptionalDiagnostic CCEDiag(const Expr *E, diag::kind DiagId + = diag::note_invalid_subexpr_in_const_expr, + unsigned ExtraNotes = 0) { + return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes); + } /// Add a note to a prior diagnostic. OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId) { if (!HasActiveDiagnostic) @@ -763,6 +778,29 @@ namespace { llvm_unreachable("Missed EvalMode case"); } + /// Notes that we failed to evaluate an expression that other expressions + /// directly depend on, and determine if we should keep evaluating. This + /// should only be called if we actually intend to keep evaluating. + /// + /// Call noteSideEffect() instead if we may be able to ignore the value that + /// we failed to evaluate, e.g. if we failed to evaluate Foo() in: + /// + /// (Foo(), 1) // use noteSideEffect + /// (Foo() || true) // use noteSideEffect + /// Foo() + 1 // use noteFailure + LLVM_ATTRIBUTE_UNUSED_RESULT bool noteFailure() { + // Failure when evaluating some expression often means there is some + // subexpression whose evaluation was skipped. Therefore, (because we + // don't track whether we skipped an expression when unwinding after an + // evaluation failure) every evaluation failure that bubbles up from a + // subexpression implies that a side-effect has potentially happened. We + // skip setting the HasSideEffects flag to true until we decide to + // continue evaluating after that point, which happens here. + bool KeepGoing = keepEvaluatingAfterFailure(); + EvalStatus.HasSideEffects |= KeepGoing; + return KeepGoing; + } + bool allowInvalidBaseExpr() const { return EvalMode == EM_DesignatorFold; } @@ -811,24 +849,52 @@ namespace { ~FoldOffsetRAII() { Info.EvalMode = OldMode; } }; - /// RAII object used to suppress diagnostics and side-effects from a - /// speculative evaluation. + /// RAII object used to optionally suppress diagnostics and side-effects from + /// a speculative evaluation. class SpeculativeEvaluationRAII { - EvalInfo &Info; + /// Pair of EvalInfo, and a bit that stores whether or not we were + /// speculatively evaluating when we created this RAII. + llvm::PointerIntPair<EvalInfo *, 1, bool> InfoAndOldSpecEval; Expr::EvalStatus Old; + void moveFromAndCancel(SpeculativeEvaluationRAII &&Other) { + InfoAndOldSpecEval = Other.InfoAndOldSpecEval; + Old = Other.Old; + Other.InfoAndOldSpecEval.setPointer(nullptr); + } + + void maybeRestoreState() { + EvalInfo *Info = InfoAndOldSpecEval.getPointer(); + if (!Info) + return; + + Info->EvalStatus = Old; + Info->IsSpeculativelyEvaluating = InfoAndOldSpecEval.getInt(); + } + public: - SpeculativeEvaluationRAII(EvalInfo &Info, - SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr) - : Info(Info), Old(Info.EvalStatus) { + SpeculativeEvaluationRAII() = default; + + SpeculativeEvaluationRAII( + EvalInfo &Info, SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr) + : InfoAndOldSpecEval(&Info, Info.IsSpeculativelyEvaluating), + Old(Info.EvalStatus) { Info.EvalStatus.Diag = NewDiag; - // If we're speculatively evaluating, we may have skipped over some - // evaluations and missed out a side effect. - Info.EvalStatus.HasSideEffects = true; + Info.IsSpeculativelyEvaluating = true; } - ~SpeculativeEvaluationRAII() { - Info.EvalStatus = Old; + + SpeculativeEvaluationRAII(const SpeculativeEvaluationRAII &Other) = delete; + SpeculativeEvaluationRAII(SpeculativeEvaluationRAII &&Other) { + moveFromAndCancel(std::move(Other)); } + + SpeculativeEvaluationRAII &operator=(SpeculativeEvaluationRAII &&Other) { + maybeRestoreState(); + moveFromAndCancel(std::move(Other)); + return *this; + } + + ~SpeculativeEvaluationRAII() { maybeRestoreState(); } }; /// RAII object wrapping a full-expression or block scope, and handling @@ -941,6 +1007,16 @@ void EvalInfo::addCallStack(unsigned Limit) { continue; } + // Use a different note for an inheriting constructor, because from the + // user's perspective it's not really a function at all. + if (auto *CD = dyn_cast_or_null<CXXConstructorDecl>(Frame->Callee)) { + if (CD->isInheritingConstructor()) { + addDiag(Frame->CallLoc, diag::note_constexpr_inherited_ctor_call_here) + << CD->getParent(); + continue; + } + } + SmallVector<char, 128> Buffer; llvm::raw_svector_ostream Out(Buffer); describeCall(Frame, Out); @@ -992,7 +1068,7 @@ namespace { struct LValue { APValue::LValueBase Base; CharUnits Offset; - bool InvalidBase : 1; + unsigned InvalidBase : 1; unsigned CallIndex : 31; SubobjectDesignator Designator; @@ -1335,12 +1411,12 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, if (!IsGlobalLValue(Base)) { if (Info.getLangOpts().CPlusPlus11) { const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); - Info.Diag(Loc, diag::note_constexpr_non_global, 1) + Info.FFDiag(Loc, diag::note_constexpr_non_global, 1) << IsReferenceType << !Designator.Entries.empty() << !!VD << VD; NoteLValueLocation(Info, Base); } else { - Info.Diag(Loc); + Info.FFDiag(Loc); } // Don't allow references to temporaries to escape. return false; @@ -1390,7 +1466,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, // Does this refer one past the end of some object? if (!Designator.Invalid && Designator.isOnePastTheEnd()) { const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); - Info.Diag(Loc, diag::note_constexpr_past_end, 1) + Info.FFDiag(Loc, diag::note_constexpr_past_end, 1) << !Designator.Entries.empty() << !!VD << VD; NoteLValueLocation(Info, Base); } @@ -1414,10 +1490,10 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E, // Prvalue constant expressions must be of literal types. if (Info.getLangOpts().CPlusPlus11) - Info.Diag(E, diag::note_constexpr_nonliteral) + Info.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType(); else - Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -1427,7 +1503,7 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E, static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, QualType Type, const APValue &Value) { if (Value.isUninit()) { - Info.Diag(DiagLoc, diag::note_constexpr_uninitialized) + Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) << true << Type; return false; } @@ -1637,7 +1713,7 @@ static bool truncateBitfieldValue(EvalInfo &Info, const Expr *E, // FIXME: In this case, we should provide the diagnostic for casting // a pointer to an integer. assert(Value.isLValue() && "integral value neither int nor lvalue?"); - Info.Diag(E); + Info.FFDiag(E); return false; } @@ -1679,7 +1755,7 @@ static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E, } else { // Don't try to handle vectors of anything other than int or float // (not sure if it's possible to hit this case). - Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } unsigned BaseEltSize = EltAsInt.getBitWidth(); @@ -1692,7 +1768,7 @@ static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E, } // Give up if the input isn't an int, float, or vector. For example, we // reject "(v4i16)(intptr_t)&a". - Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -1728,7 +1804,7 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, APSInt &Result) { switch (Opcode) { default: - Info.Diag(E); + Info.FFDiag(E); return false; case BO_Mul: return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2, @@ -1745,7 +1821,7 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, case BO_Div: case BO_Rem: if (RHS == 0) { - Info.Diag(E, diag::note_expr_divide_by_zero); + Info.FFDiag(E, diag::note_expr_divide_by_zero); return false; } Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS); @@ -1826,7 +1902,7 @@ static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E, const APFloat &RHS) { switch (Opcode) { default: - Info.Diag(E); + Info.FFDiag(E); return false; case BO_Mul: LHS.multiply(RHS, APFloat::rmNearestTiesToEven); @@ -1968,10 +2044,15 @@ static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc, return true; } + if (Type->isDependentType()) { + Info.FFDiag(Loc); + return false; + } + if (!Type->isConstantSizeType()) { // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. // FIXME: Better diagnostic. - Info.Diag(Loc); + Info.FFDiag(Loc); return false; } @@ -2035,7 +2116,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, if (Info.checkingPotentialConstantExpression()) return false; if (!Frame || !Frame->Arguments) { - Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } Result = &Frame->Arguments[PVD->getFunctionScopeIndex()]; @@ -2045,7 +2126,22 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, // If this is a local variable, dig out its value. if (Frame) { Result = Frame->getTemporary(VD); - assert(Result && "missing value for local variable"); + if (!Result) { + // Assume variables referenced within a lambda's call operator that were + // not declared within the call operator are captures and during checking + // of a potential constant expression, assume they are unknown constant + // expressions. + assert(isLambdaCallOperator(Frame->Callee) && + (VD->getDeclContext() != Frame->Callee || VD->isInitCapture()) && + "missing value for local variable"); + if (Info.checkingPotentialConstantExpression()) + return false; + // FIXME: implement capture evaluation during constant expr evaluation. + Info.FFDiag(E->getLocStart(), + diag::note_unimplemented_constexpr_lambda_feature_ast) + << "captures not currently allowed"; + return false; + } return true; } @@ -2055,7 +2151,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, // If we're checking a potential constant expression, the variable could be // initialized later. if (!Info.checkingPotentialConstantExpression()) - Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -2069,7 +2165,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, // Never evaluate the initializer of a weak variable. We can't be sure that // this is the definition which will be used. if (VD->isWeak()) { - Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -2077,7 +2173,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, // this in the cases where it matters for conformance. SmallVector<PartialDiagnosticAt, 8> Notes; if (!VD->evaluateValue(Notes)) { - Info.Diag(E, diag::note_constexpr_var_init_non_constant, + Info.FFDiag(E, diag::note_constexpr_var_init_non_constant, Notes.size() + 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); Info.addNotes(Notes); @@ -2218,7 +2314,7 @@ static bool diagnoseUnreadableFields(EvalInfo &Info, const Expr *E, // FIXME: Add core issue number for the union case. if (Field->isMutable() && (RD->isUnion() || isReadByLvalueToRvalueConversion(Field->getType()))) { - Info.Diag(E, diag::note_constexpr_ltor_mutable, 1) << Field; + Info.FFDiag(E, diag::note_constexpr_ltor_mutable, 1) << Field; Info.Note(Field->getLocation(), diag::note_declared_at); return true; } @@ -2272,10 +2368,10 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, return handler.failed(); if (Sub.isOnePastTheEnd()) { if (Info.getLangOpts().CPlusPlus11) - Info.Diag(E, diag::note_constexpr_access_past_end) + Info.FFDiag(E, diag::note_constexpr_access_past_end) << handler.AccessKind; else - Info.Diag(E); + Info.FFDiag(E); return handler.failed(); } @@ -2287,7 +2383,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) { if (O->isUninit()) { if (!Info.checkingPotentialConstantExpression()) - Info.Diag(E, diag::note_constexpr_access_uninit) << handler.AccessKind; + Info.FFDiag(E, diag::note_constexpr_access_uninit) << handler.AccessKind; return handler.failed(); } @@ -2322,10 +2418,10 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, // Note, it should not be possible to form a pointer with a valid // designator which points more than one past the end of the array. if (Info.getLangOpts().CPlusPlus11) - Info.Diag(E, diag::note_constexpr_access_past_end) + Info.FFDiag(E, diag::note_constexpr_access_past_end) << handler.AccessKind; else - Info.Diag(E); + Info.FFDiag(E); return handler.failed(); } @@ -2355,10 +2451,10 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, uint64_t Index = Sub.Entries[I].ArrayIndex; if (Index > 1) { if (Info.getLangOpts().CPlusPlus11) - Info.Diag(E, diag::note_constexpr_access_past_end) + Info.FFDiag(E, diag::note_constexpr_access_past_end) << handler.AccessKind; else - Info.Diag(E); + Info.FFDiag(E); return handler.failed(); } @@ -2378,7 +2474,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, } } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { if (Field->isMutable() && handler.AccessKind == AK_Read) { - Info.Diag(E, diag::note_constexpr_ltor_mutable, 1) + Info.FFDiag(E, diag::note_constexpr_ltor_mutable, 1) << Field; Info.Note(Field->getLocation(), diag::note_declared_at); return handler.failed(); @@ -2390,7 +2486,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, const FieldDecl *UnionField = O->getUnionField(); if (!UnionField || UnionField->getCanonicalDecl() != Field->getCanonicalDecl()) { - Info.Diag(E, diag::note_constexpr_access_inactive_union_member) + Info.FFDiag(E, diag::note_constexpr_access_inactive_union_member) << handler.AccessKind << Field << !UnionField << UnionField; return handler.failed(); } @@ -2406,11 +2502,11 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, if (ObjType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { // FIXME: Include a description of the path to the volatile subobject. - Info.Diag(E, diag::note_constexpr_access_volatile_obj, 1) + Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1) << handler.AccessKind << 2 << Field; Info.Note(Field->getLocation(), diag::note_declared_at); } else { - Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); } return handler.failed(); } @@ -2482,7 +2578,7 @@ struct ModifySubobjectHandler { bool checkConst(QualType QT) { // Assigning to a const object has undefined behavior. if (QT.isConstQualified()) { - Info.Diag(E, diag::note_constexpr_modify_const_type) << QT; + Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; return false; } return true; @@ -2501,7 +2597,7 @@ struct ModifySubobjectHandler { return false; if (!NewVal.isInt()) { // Maybe trying to write a cast pointer value into a complex? - Info.Diag(E); + Info.FFDiag(E); return false; } Value = NewVal.getInt(); @@ -2592,7 +2688,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, const LValue &LVal, QualType LValType) { if (!LVal.Base) { - Info.Diag(E, diag::note_constexpr_access_null) << AK; + Info.FFDiag(E, diag::note_constexpr_access_null) << AK; return CompleteObject(); } @@ -2600,7 +2696,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, if (LVal.CallIndex) { Frame = Info.getCallFrame(LVal.CallIndex); if (!Frame) { - Info.Diag(E, diag::note_constexpr_lifetime_ended, 1) + Info.FFDiag(E, diag::note_constexpr_lifetime_ended, 1) << AK << LVal.Base.is<const ValueDecl*>(); NoteLValueLocation(Info, LVal.Base); return CompleteObject(); @@ -2613,10 +2709,10 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, // semantics. if (LValType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) - Info.Diag(E, diag::note_constexpr_access_volatile_type) + Info.FFDiag(E, diag::note_constexpr_access_volatile_type) << AK << LValType; else - Info.Diag(E); + Info.FFDiag(E); return CompleteObject(); } @@ -2638,18 +2734,18 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, VD = VDef; } if (!VD || VD->isInvalidDecl()) { - Info.Diag(E); + Info.FFDiag(E); return CompleteObject(); } // Accesses of volatile-qualified objects are not allowed. if (BaseType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { - Info.Diag(E, diag::note_constexpr_access_volatile_obj, 1) + Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1) << AK << 1 << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { - Info.Diag(E); + Info.FFDiag(E); } return CompleteObject(); } @@ -2664,17 +2760,20 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, // evaluation. } else if (AK != AK_Read) { // All the remaining cases only permit reading. - Info.Diag(E, diag::note_constexpr_modify_global); + Info.FFDiag(E, diag::note_constexpr_modify_global); return CompleteObject(); } else if (VD->isConstexpr()) { // OK, we can read this variable. } else if (BaseType->isIntegralOrEnumerationType()) { - if (!BaseType.isConstQualified()) { + // In OpenCL if a variable is in constant address space it is a const value. + if (!(BaseType.isConstQualified() || + (Info.getLangOpts().OpenCL && + BaseType.getAddressSpace() == LangAS::opencl_constant))) { if (Info.getLangOpts().CPlusPlus) { - Info.Diag(E, diag::note_constexpr_ltor_non_const_int, 1) << VD; + Info.FFDiag(E, diag::note_constexpr_ltor_non_const_int, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { - Info.Diag(E); + Info.FFDiag(E); } return CompleteObject(); } @@ -2690,11 +2789,15 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } } else { // FIXME: Allow folding of values of any literal type in all languages. - if (Info.getLangOpts().CPlusPlus11) { - Info.Diag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD; + if (Info.checkingPotentialConstantExpression() && + VD->getType().isConstQualified() && !VD->hasDefinition(Info.Ctx)) { + // The definition of this variable could be constexpr. We can't + // access it right now, but may be able to in future. + } else if (Info.getLangOpts().CPlusPlus11) { + Info.FFDiag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { - Info.Diag(E); + Info.FFDiag(E); } return CompleteObject(); } @@ -2730,7 +2833,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, if (!(BaseType.isConstQualified() && BaseType->isIntegralOrEnumerationType()) && !(VD && VD->getCanonicalDecl() == ED->getCanonicalDecl())) { - Info.Diag(E, diag::note_constexpr_access_static_temporary, 1) << AK; + Info.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK; Info.Note(MTE->getExprLoc(), diag::note_constexpr_temporary_here); return CompleteObject(); } @@ -2738,7 +2841,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, BaseVal = Info.Ctx.getMaterializedTemporaryValue(MTE, false); assert(BaseVal && "got reference to unevaluated temporary"); } else { - Info.Diag(E); + Info.FFDiag(E); return CompleteObject(); } } else { @@ -2749,11 +2852,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, // Volatile temporary objects cannot be accessed in constant expressions. if (BaseType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { - Info.Diag(E, diag::note_constexpr_access_volatile_obj, 1) + Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1) << AK << 0; Info.Note(Base->getExprLoc(), diag::note_constexpr_temporary_here); } else { - Info.Diag(E); + Info.FFDiag(E); } return CompleteObject(); } @@ -2769,12 +2872,13 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } // In C++1y, we can't safely access any mutable state when we might be - // evaluating after an unmodeled side effect or an evaluation failure. + // evaluating after an unmodeled side effect. // // FIXME: Not all local state is mutable. Allow local constant subobjects // to be read here (but take care with 'mutable' fields). - if (Frame && Info.getLangOpts().CPlusPlus14 && - (Info.EvalStatus.HasSideEffects || Info.keepEvaluatingAfterFailure())) + if ((Frame && Info.getLangOpts().CPlusPlus14 && + Info.EvalStatus.HasSideEffects) || + (AK != AK_Read && Info.IsSpeculativelyEvaluating)) return CompleteObject(); return CompleteObject(BaseVal, BaseType); @@ -2806,7 +2910,7 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // an ICE in C, so this only matters for fold. assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?"); if (Type.isVolatileQualified()) { - Info.Diag(Conv); + Info.FFDiag(Conv); return false; } APValue Lit; @@ -2835,7 +2939,7 @@ static bool handleAssignment(EvalInfo &Info, const Expr *E, const LValue &LVal, return false; if (!Info.getLangOpts().CPlusPlus14) { - Info.Diag(E); + Info.FFDiag(E); return false; } @@ -2863,7 +2967,7 @@ struct CompoundAssignSubobjectHandler { bool checkConst(QualType QT) { // Assigning to a const object has undefined behavior. if (QT.isConstQualified()) { - Info.Diag(E, diag::note_constexpr_modify_const_type) << QT; + Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; return false; } return true; @@ -2879,13 +2983,13 @@ struct CompoundAssignSubobjectHandler { case APValue::ComplexInt: case APValue::ComplexFloat: // FIXME: Implement complex compound assignment. - Info.Diag(E); + Info.FFDiag(E); return false; case APValue::LValue: return foundPointer(Subobj, SubobjType); default: // FIXME: can this happen? - Info.Diag(E); + Info.FFDiag(E); return false; } } @@ -2896,7 +3000,7 @@ struct CompoundAssignSubobjectHandler { if (!SubobjType->isIntegerType() || !RHS.isInt()) { // We don't support compound assignment on integer-cast-to-pointer // values. - Info.Diag(E); + Info.FFDiag(E); return false; } @@ -2924,7 +3028,7 @@ struct CompoundAssignSubobjectHandler { if (PointeeType.isNull() || !RHS.isInt() || (Opcode != BO_Add && Opcode != BO_Sub)) { - Info.Diag(E); + Info.FFDiag(E); return false; } @@ -2956,7 +3060,7 @@ static bool handleCompoundAssignment( return false; if (!Info.getLangOpts().CPlusPlus14) { - Info.Diag(E); + Info.FFDiag(E); return false; } @@ -2978,7 +3082,7 @@ struct IncDecSubobjectHandler { bool checkConst(QualType QT) { // Assigning to a const object has undefined behavior. if (QT.isConstQualified()) { - Info.Diag(E, diag::note_constexpr_modify_const_type) << QT; + Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; return false; } return true; @@ -3010,7 +3114,7 @@ struct IncDecSubobjectHandler { return foundPointer(Subobj, SubobjType); default: // FIXME: can this happen? - Info.Diag(E); + Info.FFDiag(E); return false; } } @@ -3021,7 +3125,7 @@ struct IncDecSubobjectHandler { if (!SubobjType->isIntegerType()) { // We don't support increment / decrement on integer-cast-to-pointer // values. - Info.Diag(E); + Info.FFDiag(E); return false; } @@ -3080,7 +3184,7 @@ struct IncDecSubobjectHandler { if (const PointerType *PT = SubobjType->getAs<PointerType>()) PointeeType = PT->getPointeeType(); else { - Info.Diag(E); + Info.FFDiag(E); return false; } @@ -3105,7 +3209,7 @@ static bool handleIncDec(EvalInfo &Info, const Expr *E, const LValue &LVal, return false; if (!Info.getLangOpts().CPlusPlus14) { - Info.Diag(E); + Info.FFDiag(E); return false; } @@ -3127,7 +3231,7 @@ static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, if (Object->getType()->isLiteralType(Info.Ctx)) return EvaluateTemporary(Object, This, Info); - Info.Diag(Object, diag::note_constexpr_nonliteral) << Object->getType(); + Info.FFDiag(Object, diag::note_constexpr_nonliteral) << Object->getType(); return false; } @@ -3155,7 +3259,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, // member value, the behavior is undefined. if (!MemPtr.getDecl()) { // FIXME: Specific diagnostic. - Info.Diag(RHS); + Info.FFDiag(RHS); return nullptr; } @@ -3165,7 +3269,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, // derived-to-base path for the member pointer. if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() > LV.Designator.Entries.size()) { - Info.Diag(RHS); + Info.FFDiag(RHS); return nullptr; } unsigned PathLengthToMember = @@ -3175,7 +3279,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, LV.Designator.Entries[PathLengthToMember + I]); const CXXRecordDecl *MPDecl = MemPtr.Path[I]; if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) { - Info.Diag(RHS); + Info.FFDiag(RHS); return nullptr; } } @@ -3231,7 +3335,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, assert(BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI); if (!EvaluateObjectArgument(Info, BO->getLHS(), LV)) { - if (Info.keepEvaluatingAfterFailure()) { + if (Info.noteFailure()) { MemberPtr MemPtr; EvaluateMemberPointer(BO->getRHS(), MemPtr, Info); } @@ -3309,7 +3413,7 @@ static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { const Expr *InitE = VD->getInit(); if (!InitE) { - Info.Diag(D->getLocStart(), diag::note_constexpr_uninitialized) + Info.FFDiag(D->getLocStart(), diag::note_constexpr_uninitialized) << false << VD->getType(); Val = APValue(); return false; @@ -3338,6 +3442,7 @@ static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, return EvaluateAsBooleanCondition(Cond, Result, Info); } +namespace { /// \brief A location where the result (returned value) of evaluating a /// statement should be stored. struct StmtResult { @@ -3346,6 +3451,7 @@ struct StmtResult { /// The location containing the result, if any (used to support RVO). const LValue *Slot; }; +} static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const Stmt *S, @@ -3379,6 +3485,11 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, APSInt Value; { FullExpressionRAII Scope(Info); + if (const Stmt *Init = SS->getInit()) { + EvalStmtResult ESR = EvaluateStmt(Result, Info, Init); + if (ESR != ESR_Succeeded) + return ESR; + } if (SS->getConditionVariable() && !EvaluateDecl(Info, SS->getConditionVariable())) return ESR_Failed; @@ -3421,7 +3532,7 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, case ESR_CaseNotFound: // This can only happen if the switch case is nested within a statement // expression. We have no intention of supporting that. - Info.Diag(Found->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); + Info.FFDiag(Found->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); return ESR_Failed; } llvm_unreachable("Invalid EvalStmtResult!"); @@ -3512,7 +3623,7 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, return ESR_Succeeded; } - Info.Diag(S->getLocStart()); + Info.FFDiag(S->getLocStart()); return ESR_Failed; case Stmt::NullStmtClass: @@ -3525,7 +3636,7 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, // FIXME: This isn't quite right; if we're performing aggregate // initialization, each braced subexpression is its own full-expression. FullExpressionRAII Scope(Info); - if (!EvaluateDecl(Info, DclIt) && !Info.keepEvaluatingAfterFailure()) + if (!EvaluateDecl(Info, DclIt) && !Info.noteFailure()) return ESR_Failed; } return ESR_Succeeded; @@ -3561,6 +3672,11 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, // Evaluate the condition, as either a var decl or as an expression. BlockScopeRAII Scope(Info); + if (const Stmt *Init = IS->getInit()) { + EvalStmtResult ESR = EvaluateStmt(Result, Info, Init); + if (ESR != ESR_Succeeded) + return ESR; + } bool Cond; if (!EvaluateCond(Info, IS->getConditionVariable(), IS->getCond(), Cond)) return ESR_Failed; @@ -3647,7 +3763,10 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, return ESR; // Create the __begin and __end iterators. - ESR = EvaluateStmt(Result, Info, FS->getBeginEndStmt()); + ESR = EvaluateStmt(Result, Info, FS->getBeginStmt()); + if (ESR != ESR_Succeeded) + return ESR; + ESR = EvaluateStmt(Result, Info, FS->getEndStmt()); if (ESR != ESR_Succeeded) return ESR; @@ -3736,7 +3855,8 @@ static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc, /// expression. static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Declaration, - const FunctionDecl *Definition) { + const FunctionDecl *Definition, + const Stmt *Body) { // Potential constant expressions can contain calls to declared, but not yet // defined, constexpr functions. if (Info.checkingPotentialConstantExpression() && !Definition && @@ -3749,19 +3869,34 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, return false; // Can we evaluate this function call? - if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()) + if (Definition && Definition->isConstexpr() && + !Definition->isInvalidDecl() && Body) return true; if (Info.getLangOpts().CPlusPlus11) { const FunctionDecl *DiagDecl = Definition ? Definition : Declaration; - // FIXME: If DiagDecl is an implicitly-declared special member function, we - // should be much more explicit about why it's not constexpr. - Info.Diag(CallLoc, diag::note_constexpr_invalid_function, 1) - << DiagDecl->isConstexpr() << isa<CXXConstructorDecl>(DiagDecl) - << DiagDecl; + + // If this function is not constexpr because it is an inherited + // non-constexpr constructor, diagnose that directly. + auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl); + if (CD && CD->isInheritingConstructor()) { + auto *Inherited = CD->getInheritedConstructor().getConstructor(); + if (!Inherited->isConstexpr()) + DiagDecl = CD = Inherited; + } + + // FIXME: If DiagDecl is an implicitly-declared special member function + // or an inheriting constructor, we should be much more explicit about why + // it's not constexpr. + if (CD && CD->isInheritingConstructor()) + Info.FFDiag(CallLoc, diag::note_constexpr_invalid_inhctor, 1) + << CD->getInheritedConstructor().getConstructor()->getParent(); + else + Info.FFDiag(CallLoc, diag::note_constexpr_invalid_function, 1) + << DiagDecl->isConstexpr() << (bool)CD << DiagDecl; Info.Note(DiagDecl->getLocation(), diag::note_declared_at); } else { - Info.Diag(CallLoc, diag::note_invalid_subexpr_in_const_expr); + Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr); } return false; } @@ -3795,7 +3930,7 @@ static bool EvaluateArgs(ArrayRef<const Expr*> Args, ArgVector &ArgValues, if (!Evaluate(ArgValues[I - Args.begin()], Info, *I)) { // If we're checking for a potential constant expression, evaluate all // initializers even if some of them fail. - if (!Info.keepEvaluatingAfterFailure()) + if (!Info.noteFailure()) return false; Success = false; } @@ -3848,37 +3983,34 @@ static bool HandleFunctionCall(SourceLocation CallLoc, if (ESR == ESR_Succeeded) { if (Callee->getReturnType()->isVoidType()) return true; - Info.Diag(Callee->getLocEnd(), diag::note_constexpr_no_return); + Info.FFDiag(Callee->getLocEnd(), diag::note_constexpr_no_return); } return ESR == ESR_Returned; } /// Evaluate a constructor call. -static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, - ArrayRef<const Expr*> Args, +static bool HandleConstructorCall(const Expr *E, const LValue &This, + APValue *ArgValues, const CXXConstructorDecl *Definition, EvalInfo &Info, APValue &Result) { - ArgVector ArgValues(Args.size()); - if (!EvaluateArgs(Args, ArgValues, Info)) - return false; - + SourceLocation CallLoc = E->getExprLoc(); if (!Info.CheckCallLimit(CallLoc)) return false; const CXXRecordDecl *RD = Definition->getParent(); if (RD->getNumVBases()) { - Info.Diag(CallLoc, diag::note_constexpr_virtual_base) << RD; + Info.FFDiag(CallLoc, diag::note_constexpr_virtual_base) << RD; return false; } - CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues.data()); + CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues); // 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 it's a delegating constructor, delegate. if (Definition->isDelegatingConstructor()) { CXXConstructorDecl::init_const_iterator I = Definition->init_begin(); { @@ -3902,8 +4034,9 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, (Definition->isTrivial() && hasFields(Definition->getParent())))) { LValue RHS; RHS.setFrom(Info.Ctx, ArgValues[0]); - return handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), - RHS, Result); + return handleLValueToRValueConversion( + Info, E, Definition->getParamDecl(0)->getType().getNonReferenceType(), + RHS, Result); } // Reserve space for the struct members. @@ -3987,7 +4120,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, *Value, FD))) { // If we're checking for a potential constant expression, evaluate all // initializers even if some of them fail. - if (!Info.keepEvaluatingAfterFailure()) + if (!Info.noteFailure()) return false; Success = false; } @@ -3997,6 +4130,18 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed; } +static bool HandleConstructorCall(const Expr *E, const LValue &This, + ArrayRef<const Expr*> Args, + const CXXConstructorDecl *Definition, + EvalInfo &Info, APValue &Result) { + ArgVector ArgValues(Args.size()); + if (!EvaluateArgs(Args, ArgValues, Info)) + return false; + + return HandleConstructorCall(E, This, ArgValues.data(), Definition, + Info, Result); +} + //===----------------------------------------------------------------------===// // Generic Evaluation //===----------------------------------------------------------------------===// @@ -4022,14 +4167,16 @@ private: assert(Info.checkingPotentialConstantExpression()); // Speculatively evaluate both arms. + SmallVector<PartialDiagnosticAt, 8> Diag; { - SmallVector<PartialDiagnosticAt, 8> Diag; SpeculativeEvaluationRAII Speculate(Info, &Diag); - StmtVisitorTy::Visit(E->getFalseExpr()); if (Diag.empty()) return; + } + { + SpeculativeEvaluationRAII Speculate(Info, &Diag); Diag.clear(); StmtVisitorTy::Visit(E->getTrueExpr()); if (Diag.empty()) @@ -4044,7 +4191,7 @@ private: bool HandleConditionalOperator(const ConditionalOperator *E) { bool BoolResult; if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info)) { - if (Info.checkingPotentialConstantExpression()) + if (Info.checkingPotentialConstantExpression() && Info.noteFailure()) CheckPotentialConstantConditional(E); return false; } @@ -4072,7 +4219,7 @@ public: /// Report an evaluation error. This should only be called when an error is /// first discovered. When propagating an error, just return false. bool Error(const Expr *E, diag::kind D) { - Info.Diag(E, D); + Info.FFDiag(E, D); return false; } bool Error(const Expr *E) { @@ -4275,7 +4422,7 @@ public: const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) || + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, Result, ResultSlot)) return false; @@ -4397,7 +4544,7 @@ public: if (BI + 1 == BE) { const Expr *FinalExpr = dyn_cast<Expr>(*BI); if (!FinalExpr) { - Info.Diag((*BI)->getLocStart(), + Info.FFDiag((*BI)->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); return false; } @@ -4412,7 +4559,7 @@ public: // 'break', or 'continue', it would be nice to propagate that to // the outer statement evaluation rather than bailing out. if (ESR != ESR_Failed) - Info.Diag((*BI)->getLocStart(), + Info.FFDiag((*BI)->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); return false; } @@ -4425,6 +4572,15 @@ public: void VisitIgnoredValue(const Expr *E) { EvaluateIgnoredValue(Info, E); } + + /// Potentially visit a MemberExpr's base expression. + void VisitIgnoredBaseExpression(const Expr *E) { + // While MSVC doesn't evaluate the base expression, it does diagnose the + // presence of side-effecting behavior. + if (Info.getLangOpts().MSVCCompat && !E->HasSideEffects(Info.Ctx)) + return; + VisitIgnoredValue(E); + } }; } @@ -4651,7 +4807,7 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { return false; if (V->isUninit()) { if (!Info.checkingPotentialConstantExpression()) - Info.Diag(E, diag::note_constexpr_use_uninit_reference); + Info.FFDiag(E, diag::note_constexpr_use_uninit_reference); return false; } return Success(*V, E); @@ -4735,7 +4891,7 @@ bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) { if (!E->isPotentiallyEvaluated()) return Success(E); - Info.Diag(E, diag::note_constexpr_typeid_polymorphic) + Info.FFDiag(E, diag::note_constexpr_typeid_polymorphic) << E->getExprOperand()->getType() << E->getExprOperand()->getSourceRange(); return false; @@ -4748,14 +4904,14 @@ bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { // Handle static data members. if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) { - VisitIgnoredValue(E->getBase()); + VisitIgnoredBaseExpression(E->getBase()); return VisitVarDecl(E, VD); } // Handle static member functions. if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl())) { if (MD->isStatic()) { - VisitIgnoredValue(E->getBase()); + VisitIgnoredBaseExpression(E->getBase()); return Success(MD); } } @@ -4823,7 +4979,7 @@ bool LValueExprEvaluator::VisitCompoundAssignOperator( // The overall lvalue result is the result of evaluating the LHS. if (!this->Visit(CAO->getLHS())) { - if (Info.keepEvaluatingAfterFailure()) + if (Info.noteFailure()) Evaluate(RHS, this->Info, CAO->getRHS()); return false; } @@ -4844,7 +5000,7 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { APValue NewVal; if (!this->Visit(E->getLHS())) { - if (Info.keepEvaluatingAfterFailure()) + if (Info.noteFailure()) Evaluate(NewVal, this->Info, E->getRHS()); return false; } @@ -4903,9 +5059,9 @@ public: return false; if (!Info.CurrentCall->This) { if (Info.getLangOpts().CPlusPlus11) - Info.Diag(E, diag::note_constexpr_this) << E->isImplicit(); + Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit(); else - Info.Diag(E); + Info.FFDiag(E); return false; } Result = *Info.CurrentCall->This; @@ -4932,7 +5088,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { std::swap(PExp, IExp); bool EvalPtrOK = EvaluatePointer(PExp, Result, Info); - if (!EvalPtrOK && !Info.keepEvaluatingAfterFailure()) + if (!EvalPtrOK && !Info.noteFailure()) return false; llvm::APSInt Offset; @@ -5135,7 +5291,7 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { } // The offset must also have the correct alignment. - if (OffsetResult.Offset.RoundUpToAlignment(Align) != OffsetResult.Offset) { + if (OffsetResult.Offset.alignTo(Align) != OffsetResult.Offset) { Result.Designator.setInvalid(); APSInt Offset(64, false); Offset = OffsetResult.Offset.getQuantity(); @@ -5265,14 +5421,21 @@ namespace { Result = V; return true; } - bool ZeroInitialization(const Expr *E); + bool ZeroInitialization(const Expr *E) { + return ZeroInitialization(E, E->getType()); + } + bool ZeroInitialization(const Expr *E, QualType T); 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); + bool VisitCXXConstructExpr(const CXXConstructExpr *E) { + return VisitCXXConstructExpr(E, E->getType()); + } + bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); + bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T); bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); }; } @@ -5327,8 +5490,8 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E, return true; } -bool RecordExprEvaluator::ZeroInitialization(const Expr *E) { - const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl(); +bool RecordExprEvaluator::ZeroInitialization(const Expr *E, QualType T) { + const RecordDecl *RD = T->castAs<RecordType>()->getDecl(); if (RD->isInvalidDecl()) return false; if (RD->isUnion()) { // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the @@ -5348,7 +5511,7 @@ bool RecordExprEvaluator::ZeroInitialization(const Expr *E) { } if (isa<CXXRecordDecl>(RD) && cast<CXXRecordDecl>(RD)->getNumVBases()) { - Info.Diag(E, diag::note_constexpr_virtual_base) << RD; + Info.FFDiag(E, diag::note_constexpr_virtual_base) << RD; return false; } @@ -5417,12 +5580,34 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr); } - assert((!isa<CXXRecordDecl>(RD) || !cast<CXXRecordDecl>(RD)->getNumBases()) && - "initializer list for class with base classes"); - Result = APValue(APValue::UninitStruct(), 0, - std::distance(RD->field_begin(), RD->field_end())); + auto *CXXRD = dyn_cast<CXXRecordDecl>(RD); + if (Result.isUninit()) + Result = APValue(APValue::UninitStruct(), CXXRD ? CXXRD->getNumBases() : 0, + std::distance(RD->field_begin(), RD->field_end())); unsigned ElementNo = 0; bool Success = true; + + // Initialize base classes. + if (CXXRD) { + for (const auto &Base : CXXRD->bases()) { + assert(ElementNo < E->getNumInits() && "missing init for base class"); + const Expr *Init = E->getInit(ElementNo); + + LValue Subobject = This; + if (!HandleLValueBase(Info, Init, Subobject, CXXRD, &Base)) + return false; + + APValue &FieldVal = Result.getStructBase(ElementNo); + if (!EvaluateInPlace(FieldVal, Info, Subobject, Init)) { + if (!Info.noteFailure()) + return false; + Success = false; + } + ++ElementNo; + } + } + + // Initialize members. for (const auto *Field : RD->fields()) { // Anonymous bit-fields are not considered members of the class for // purposes of aggregate initialization. @@ -5452,7 +5637,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) || (Field->isBitField() && !truncateBitfieldValue(Info, Init, FieldVal, Field))) { - if (!Info.keepEvaluatingAfterFailure()) + if (!Info.noteFailure()) return false; Success = false; } @@ -5461,7 +5646,10 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { return Success; } -bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { +bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, + QualType T) { + // Note that E's type is not necessarily the type of our class here; we might + // be initializing an array element instead. const CXXConstructorDecl *FD = E->getConstructor(); if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl()) return false; @@ -5479,13 +5667,13 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { // lifetimes of all the base subobjects (there can be no data member // subobjects in this case) per [basic.life]p1. // Either way, ZeroInitialization is appropriate. - return ZeroInitialization(E); + return ZeroInitialization(E, T); } const FunctionDecl *Definition = nullptr; - FD->getBody(Definition); + auto Body = FD->getBody(Definition); - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; // Avoid materializing a temporary for an elidable copy/move constructor. @@ -5494,11 +5682,33 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { = dyn_cast<MaterializeTemporaryExpr>(E->getArg(0))) return Visit(ME->GetTemporaryExpr()); - if (ZeroInit && !ZeroInitialization(E)) + if (ZeroInit && !ZeroInitialization(E, T)) return false; auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); - return HandleConstructorCall(E->getExprLoc(), This, Args, + return HandleConstructorCall(E, This, Args, + cast<CXXConstructorDecl>(Definition), Info, + Result); +} + +bool RecordExprEvaluator::VisitCXXInheritedCtorInitExpr( + const CXXInheritedCtorInitExpr *E) { + if (!Info.CurrentCall) { + assert(Info.checkingPotentialConstantExpression()); + return false; + } + + const CXXConstructorDecl *FD = E->getConstructor(); + if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl()) + return false; + + const FunctionDecl *Definition = nullptr; + auto Body = FD->getBody(Definition); + + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) + return false; + + return HandleConstructorCall(E, This, Info.CurrentCall->Arguments, cast<CXXConstructorDecl>(Definition), Info, Result); } @@ -5902,7 +6112,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { Info, Subobject, Init) || !HandleLValueArrayAdjustment(Info, Init, Subobject, CAT->getElementType(), 1)) { - if (!Info.keepEvaluatingAfterFailure()) + if (!Info.noteFailure()) return false; Success = false; } @@ -5958,34 +6168,8 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, if (!Type->isRecordType()) return Error(E); - const CXXConstructorDecl *FD = E->getConstructor(); - - bool ZeroInit = E->requiresZeroInitialization(); - if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) { - if (HadZeroInit) - return true; - - // See RecordExprEvaluator::VisitCXXConstructExpr for explanation. - ImplicitValueInitExpr VIE(Type); - return EvaluateInPlace(*Value, Info, Subobject, &VIE); - } - - const FunctionDecl *Definition = nullptr; - FD->getBody(Definition); - - if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) - return false; - - if (ZeroInit && !HadZeroInit) { - ImplicitValueInitExpr VIE(Type); - if (!EvaluateInPlace(*Value, Info, Subobject, &VIE)) - return false; - } - - auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); - return HandleConstructorCall(E->getExprLoc(), Subobject, Args, - cast<CXXConstructorDecl>(Definition), - Info, *Value); + return RecordExprEvaluator(Info, Subobject, *Value) + .VisitCXXConstructExpr(E, Type); } //===----------------------------------------------------------------------===// @@ -6076,7 +6260,7 @@ public: } bool VisitMemberExpr(const MemberExpr *E) { if (CheckReferencedDecl(E, E->getMemberDecl())) { - VisitIgnoredValue(E->getBase()); + VisitIgnoredBaseExpression(E->getBase()); return true; } @@ -6149,7 +6333,7 @@ static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info) { if (!Val.isInt()) { // FIXME: It would be better to produce the diagnostic for casting // a pointer to an integer. - Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } Result = Val.getInt(); @@ -6185,7 +6369,8 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { /// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way /// as GCC. -static int EvaluateBuiltinClassifyType(const CallExpr *E) { +static int EvaluateBuiltinClassifyType(const CallExpr *E, + const LangOptions &LangOpts) { // The following enum mimics the values returned by GCC. // FIXME: Does GCC differ between lvalue and rvalue references here? enum gcc_type_class { @@ -6205,37 +6390,123 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E) { if (E->getNumArgs() == 0) return no_type_class; - QualType ArgTy = E->getArg(0)->getType(); - if (ArgTy->isVoidType()) - return void_type_class; - else if (ArgTy->isEnumeralType()) - return enumeral_type_class; - else if (ArgTy->isBooleanType()) - return boolean_type_class; - else if (ArgTy->isCharType()) - return string_type_class; // gcc doesn't appear to use char_type_class - else if (ArgTy->isIntegerType()) - return integer_type_class; - else if (ArgTy->isPointerType()) + QualType CanTy = E->getArg(0)->getType().getCanonicalType(); + const BuiltinType *BT = dyn_cast<BuiltinType>(CanTy); + + switch (CanTy->getTypeClass()) { +#define TYPE(ID, BASE) +#define DEPENDENT_TYPE(ID, BASE) case Type::ID: +#define NON_CANONICAL_TYPE(ID, BASE) case Type::ID: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(ID, BASE) case Type::ID: +#include "clang/AST/TypeNodes.def" + llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); + + case Type::Builtin: + switch (BT->getKind()) { +#define BUILTIN_TYPE(ID, SINGLETON_ID) +#define SIGNED_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: return integer_type_class; +#define FLOATING_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: return real_type_class; +#define PLACEHOLDER_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: break; +#include "clang/AST/BuiltinTypes.def" + case BuiltinType::Void: + return void_type_class; + + case BuiltinType::Bool: + return boolean_type_class; + + case BuiltinType::Char_U: // gcc doesn't appear to use char_type_class + case BuiltinType::UChar: + case BuiltinType::UShort: + case BuiltinType::UInt: + case BuiltinType::ULong: + case BuiltinType::ULongLong: + case BuiltinType::UInt128: + return integer_type_class; + + case BuiltinType::NullPtr: + return pointer_type_class; + + case BuiltinType::WChar_U: + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" + case BuiltinType::OCLSampler: + case BuiltinType::OCLEvent: + case BuiltinType::OCLClkEvent: + case BuiltinType::OCLQueue: + case BuiltinType::OCLNDRange: + case BuiltinType::OCLReserveID: + case BuiltinType::Dependent: + llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); + }; + + case Type::Enum: + return LangOpts.CPlusPlus ? enumeral_type_class : integer_type_class; + break; + + case Type::Pointer: return pointer_type_class; - else if (ArgTy->isReferenceType()) - return reference_type_class; - else if (ArgTy->isRealType()) - return real_type_class; - else if (ArgTy->isComplexType()) + break; + + case Type::MemberPointer: + if (CanTy->isMemberDataPointerType()) + return offset_type_class; + else { + // We expect member pointers to be either data or function pointers, + // nothing else. + assert(CanTy->isMemberFunctionPointerType()); + return method_type_class; + } + + case Type::Complex: return complex_type_class; - else if (ArgTy->isFunctionType()) - return function_type_class; - else if (ArgTy->isStructureOrClassType()) - return record_type_class; - else if (ArgTy->isUnionType()) - return union_type_class; - else if (ArgTy->isArrayType()) - return array_type_class; - else if (ArgTy->isUnionType()) - return union_type_class; - else // FIXME: offset_type_class, method_type_class, & lang_type_class? + + case Type::FunctionNoProto: + case Type::FunctionProto: + return LangOpts.CPlusPlus ? function_type_class : pointer_type_class; + + case Type::Record: + if (const RecordType *RT = CanTy->getAs<RecordType>()) { + switch (RT->getDecl()->getTagKind()) { + case TagTypeKind::TTK_Struct: + case TagTypeKind::TTK_Class: + case TagTypeKind::TTK_Interface: + return record_type_class; + + case TagTypeKind::TTK_Enum: + return LangOpts.CPlusPlus ? enumeral_type_class : integer_type_class; + + case TagTypeKind::TTK_Union: + return union_type_class; + } + } + llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); + + case Type::ConstantArray: + case Type::VariableArray: + case Type::IncompleteArray: + return LangOpts.CPlusPlus ? array_type_class : pointer_type_class; + + case Type::BlockPointer: + case Type::LValueReference: + case Type::RValueReference: + case Type::Vector: + case Type::ExtVector: + case Type::Auto: + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + case Type::Pipe: + case Type::Atomic: llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); + } + + llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); } /// EvaluateBuiltinConstantPForLValue - Determine the result of @@ -6346,25 +6617,32 @@ static const Expr *ignorePointerCastsAndParens(const Expr *E) { /// /// Please note: this function is specialized for how __builtin_object_size /// views "objects". +/// +/// If this encounters an invalid RecordDecl, it will always return true. static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { assert(!LVal.Designator.Invalid); - auto IsLastFieldDecl = [&Ctx](const FieldDecl *FD) { - if (FD->getParent()->isUnion()) + auto IsLastOrInvalidFieldDecl = [&Ctx](const FieldDecl *FD, bool &Invalid) { + const RecordDecl *Parent = FD->getParent(); + Invalid = Parent->isInvalidDecl(); + if (Invalid || Parent->isUnion()) return true; - const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(FD->getParent()); + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Parent); 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; + bool Invalid; + if (!IsLastOrInvalidFieldDecl(FD, Invalid)) + return Invalid; } else if (auto *IFD = dyn_cast<IndirectFieldDecl>(ME->getMemberDecl())) { - for (auto *FD : IFD->chain()) - if (!IsLastFieldDecl(cast<FieldDecl>(FD))) - return false; + for (auto *FD : IFD->chain()) { + bool Invalid; + if (!IsLastOrInvalidFieldDecl(cast<FieldDecl>(FD), Invalid)) + return Invalid; + } } } @@ -6387,8 +6665,9 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { return false; BaseType = CT->getElementType(); } else if (auto *FD = getAsField(LVal.Designator.Entries[I])) { - if (!IsLastFieldDecl(FD)) - return false; + bool Invalid; + if (!IsLastOrInvalidFieldDecl(FD, Invalid)) + return Invalid; BaseType = FD->getType(); } else { assert(getAsBaseClass(LVal.Designator.Entries[I]) != nullptr && @@ -6607,7 +6886,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { } case Builtin::BI__builtin_classify_type: - return Success(EvaluateBuiltinClassifyType(E), E); + return Success(EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E); // FIXME: BI__builtin_clrsb // FIXME: BI__builtin_clrsbl @@ -6899,23 +7178,14 @@ class DataRecursiveIntBinOpEvaluator { Job() = default; Job(Job &&J) : E(J.E), LHSResult(J.LHSResult), Kind(J.Kind), - StoredInfo(J.StoredInfo), OldEvalStatus(J.OldEvalStatus) { - J.StoredInfo = nullptr; - } + SpecEvalRAII(std::move(J.SpecEvalRAII)) {} void startSpeculativeEval(EvalInfo &Info) { - OldEvalStatus = Info.EvalStatus; - Info.EvalStatus.Diag = nullptr; - StoredInfo = &Info; - } - ~Job() { - if (StoredInfo) { - StoredInfo->EvalStatus = OldEvalStatus; - } + SpecEvalRAII = SpeculativeEvaluationRAII(Info); } + private: - EvalInfo *StoredInfo = nullptr; // non-null if status changed. - Expr::EvalStatus OldEvalStatus; + SpeculativeEvaluationRAII SpecEvalRAII; }; SmallVector<Job, 16> Queue; @@ -6935,7 +7205,9 @@ public: static bool shouldEnqueue(const BinaryOperator *E) { return E->getOpcode() == BO_Comma || E->isLogicalOp() || - (E->getLHS()->getType()->isIntegralOrEnumerationType() && + (E->isRValue() && + E->getType()->isIntegralOrEnumerationType() && + E->getLHS()->getType()->isIntegralOrEnumerationType() && E->getRHS()->getType()->isIntegralOrEnumerationType()); } @@ -7017,7 +7289,7 @@ bool DataRecursiveIntBinOpEvaluator:: LHSResult.Failed = true; // Since we weren't able to evaluate the left hand side, it - // must have had side effects. + // might have had side effects. if (!Info.noteSideEffect()) return false; @@ -7033,7 +7305,7 @@ bool DataRecursiveIntBinOpEvaluator:: assert(E->getLHS()->getType()->isIntegralOrEnumerationType() && E->getRHS()->getType()->isIntegralOrEnumerationType()); - if (LHSResult.Failed && !Info.keepEvaluatingAfterFailure()) + if (LHSResult.Failed && !Info.noteFailure()) return false; // Ignore RHS; return true; @@ -7185,10 +7457,34 @@ void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { llvm_unreachable("Invalid Job::Kind!"); } +namespace { +/// Used when we determine that we should fail, but can keep evaluating prior to +/// noting that we had a failure. +class DelayedNoteFailureRAII { + EvalInfo &Info; + bool NoteFailure; + +public: + DelayedNoteFailureRAII(EvalInfo &Info, bool NoteFailure = true) + : Info(Info), NoteFailure(NoteFailure) {} + ~DelayedNoteFailureRAII() { + if (NoteFailure) { + bool ContinueAfterFailure = Info.noteFailure(); + (void)ContinueAfterFailure; + assert(ContinueAfterFailure && + "Shouldn't have kept evaluating on failure."); + } + } +}; +} + bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { + // We don't call noteFailure immediately because the assignment happens after + // we evaluate LHS and RHS. if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp()) return Error(E); + DelayedNoteFailureRAII MaybeNoteFailureLater(Info, E->isAssignmentOp()); if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E)) return DataRecursiveIntBinOpEvaluator(*this, Result).Traverse(E); @@ -7211,7 +7507,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { } else { LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); } - if (!LHSOK && !Info.keepEvaluatingAfterFailure()) + if (!LHSOK && !Info.noteFailure()) return false; if (E->getRHS()->getType()->isRealFloatingType()) { @@ -7259,7 +7555,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { APFloat RHS(0.0), LHS(0.0); bool LHSOK = EvaluateFloat(E->getRHS(), RHS, Info); - if (!LHSOK && !Info.keepEvaluatingAfterFailure()) + if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluateFloat(E->getLHS(), LHS, Info) || !LHSOK) @@ -7293,7 +7589,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { LValue LHSValue, RHSValue; bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info); - if (!LHSOK && !Info.keepEvaluatingAfterFailure()) + if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK) @@ -7387,7 +7683,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // C, array of zero length). Pointer subtraction in such cases has // undefined behavior, so is not constant. if (ElementSize.isZero()) { - Info.Diag(E, diag::note_constexpr_pointer_subtraction_zero_size) + Info.FFDiag(E, diag::note_constexpr_pointer_subtraction_zero_size) << ElementType; return false; } @@ -7510,7 +7806,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { MemberPtr LHSValue, RHSValue; bool LHSOK = EvaluateMemberPointer(E->getLHS(), LHSValue, Info); - if (!LHSOK && Info.keepEvaluatingAfterFailure()) + if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluateMemberPointer(E->getRHS(), RHSValue, Info) || !LHSOK) @@ -8082,7 +8378,7 @@ bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { APFloat RHS(0.0); bool LHSOK = EvaluateFloat(E->getLHS(), Result, Info); - if (!LHSOK && !Info.keepEvaluatingAfterFailure()) + if (!LHSOK && !Info.noteFailure()) return false; return EvaluateFloat(E->getRHS(), RHS, Info) && LHSOK && handleFloatFloatBinOp(Info, E, Result, E->getOpcode(), RHS); @@ -8359,7 +8655,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { } else { LHSOK = Visit(E->getLHS()); } - if (!LHSOK && !Info.keepEvaluatingAfterFailure()) + if (!LHSOK && !Info.noteFailure()) return false; ComplexValue RHS; @@ -8513,12 +8809,14 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { APFloat MaxCD = maxnum(abs(C), abs(D)); if (MaxCD.isFinite()) { DenomLogB = ilogb(MaxCD); - C = scalbn(C, -DenomLogB); - D = scalbn(D, -DenomLogB); + C = scalbn(C, -DenomLogB, APFloat::rmNearestTiesToEven); + D = scalbn(D, -DenomLogB, APFloat::rmNearestTiesToEven); } APFloat Denom = C * C + D * D; - ResR = scalbn((A * C + B * D) / Denom, -DenomLogB); - ResI = scalbn((B * C - A * D) / Denom, -DenomLogB); + ResR = scalbn((A * C + B * D) / Denom, -DenomLogB, + APFloat::rmNearestTiesToEven); + ResI = scalbn((B * C - A * D) / Denom, -DenomLogB, + APFloat::rmNearestTiesToEven); if (ResR.isNaN() && ResI.isNaN()) { if (Denom.isPosZero() && (!A.isNaN() || !B.isNaN())) { ResR = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * A; @@ -8758,10 +9056,10 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { if (!EvaluateAtomic(E, Result, Info)) return false; } else if (Info.getLangOpts().CPlusPlus11) { - Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType(); + Info.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType(); return false; } else { - Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -8885,6 +9183,20 @@ bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx, return true; } +bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx, + SideEffectsKind AllowSideEffects) const { + if (!getType()->isRealFloatingType()) + return false; + + EvalResult ExprResult; + if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isFloat() || + hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) + return false; + + Result = ExprResult.Val.getFloat(); + return true; +} + bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold); @@ -9070,6 +9382,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::TypoExprClass: case Expr::DependentScopeDeclRefExprClass: case Expr::CXXConstructExprClass: + case Expr::CXXInheritedCtorInitExprClass: case Expr::CXXStdInitializerListExprClass: case Expr::CXXBindTemporaryExprClass: case Expr::ExprWithCleanupsClass: @@ -9089,6 +9402,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::ObjCPropertyRefExprClass: case Expr::ObjCSubscriptRefExprClass: case Expr::ObjCIsaExprClass: + case Expr::ObjCAvailabilityCheckExprClass: case Expr::ShuffleVectorExprClass: case Expr::ConvertVectorExprClass: case Expr::BlockExprClass: @@ -9533,17 +9847,17 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, ArrayRef<const Expr*> Args; - SourceLocation Loc = FD->getLocation(); - APValue Scratch; if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { // Evaluate the call as a constant initializer, to allow the construction // of objects of non-literal types. Info.setEvaluatingDecl(This.getLValueBase(), Scratch); - HandleConstructorCall(Loc, This, Args, CD, Info, Scratch); - } else + HandleConstructorCall(&VIE, This, Args, CD, Info, Scratch); + } else { + SourceLocation Loc = FD->getLocation(); HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr, Args, FD->getBody(), Info, Scratch, nullptr); + } return Diags.empty(); } diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 3f6b682f238f..694fde317542 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -20,6 +20,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -66,8 +67,9 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { } const DeclContext *DC = D->getDeclContext(); - if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC)) - return getEffectiveDeclContext(CD); + if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC)) { + return getEffectiveDeclContext(cast<Decl>(DC)); + } if (const auto *VD = dyn_cast<VarDecl>(D)) if (VD->isExternC()) @@ -77,7 +79,7 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { if (FD->isExternC()) return FD->getASTContext().getTranslationUnitDecl(); - return DC; + return DC->getRedeclContext(); } static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { @@ -212,6 +214,12 @@ public: class CXXNameMangler { ItaniumMangleContextImpl &Context; raw_ostream &Out; + bool NullOut = false; + /// In the "DisableDerivedAbiTags" mode derived ABI tags are not calculated. + /// This mode is used when mangler creates another mangler recursively to + /// calculate ABI tags for the function return value or the variable type. + /// Also it is required to avoid infinite recursion in some cases. + bool DisableDerivedAbiTags = false; /// The "structor" is the top-level declaration being mangled, if /// that's not a template specialization; otherwise it's the pattern @@ -261,15 +269,126 @@ class CXXNameMangler { } FunctionTypeDepth; + // abi_tag is a gcc attribute, taking one or more strings called "tags". + // The goal is to annotate against which version of a library an object was + // built and to be able to provide backwards compatibility ("dual abi"). + // For more information see docs/ItaniumMangleAbiTags.rst. + typedef SmallVector<StringRef, 4> AbiTagList; + + // State to gather all implicit and explicit tags used in a mangled name. + // Must always have an instance of this while emitting any name to keep + // track. + class AbiTagState final { + public: + explicit AbiTagState(AbiTagState *&Head) : LinkHead(Head) { + Parent = LinkHead; + LinkHead = this; + } + + // No copy, no move. + AbiTagState(const AbiTagState &) = delete; + AbiTagState &operator=(const AbiTagState &) = delete; + + ~AbiTagState() { pop(); } + + void write(raw_ostream &Out, const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags) { + ND = cast<NamedDecl>(ND->getCanonicalDecl()); + if (!isa<FunctionDecl>(ND) && !isa<VarDecl>(ND)) { + assert( + !AdditionalAbiTags && + "only function and variables need a list of additional abi tags"); + if (const auto *NS = dyn_cast<NamespaceDecl>(ND)) { + if (const auto *AbiTag = NS->getAttr<AbiTagAttr>()) { + UsedAbiTags.insert(UsedAbiTags.end(), AbiTag->tags().begin(), + AbiTag->tags().end()); + } + // Don't emit abi tags for namespaces. + return; + } + } + + AbiTagList TagList; + if (const auto *AbiTag = ND->getAttr<AbiTagAttr>()) { + UsedAbiTags.insert(UsedAbiTags.end(), AbiTag->tags().begin(), + AbiTag->tags().end()); + TagList.insert(TagList.end(), AbiTag->tags().begin(), + AbiTag->tags().end()); + } + + if (AdditionalAbiTags) { + UsedAbiTags.insert(UsedAbiTags.end(), AdditionalAbiTags->begin(), + AdditionalAbiTags->end()); + TagList.insert(TagList.end(), AdditionalAbiTags->begin(), + AdditionalAbiTags->end()); + } + + std::sort(TagList.begin(), TagList.end()); + TagList.erase(std::unique(TagList.begin(), TagList.end()), TagList.end()); + + writeSortedUniqueAbiTags(Out, TagList); + } + + const AbiTagList &getUsedAbiTags() const { return UsedAbiTags; } + void setUsedAbiTags(const AbiTagList &AbiTags) { + UsedAbiTags = AbiTags; + } + + const AbiTagList &getEmittedAbiTags() const { + return EmittedAbiTags; + } + + const AbiTagList &getSortedUniqueUsedAbiTags() { + std::sort(UsedAbiTags.begin(), UsedAbiTags.end()); + UsedAbiTags.erase(std::unique(UsedAbiTags.begin(), UsedAbiTags.end()), + UsedAbiTags.end()); + return UsedAbiTags; + } + + private: + //! All abi tags used implicitly or explicitly. + AbiTagList UsedAbiTags; + //! All explicit abi tags (i.e. not from namespace). + AbiTagList EmittedAbiTags; + + AbiTagState *&LinkHead; + AbiTagState *Parent = nullptr; + + void pop() { + assert(LinkHead == this && + "abi tag link head must point to us on destruction"); + if (Parent) { + Parent->UsedAbiTags.insert(Parent->UsedAbiTags.end(), + UsedAbiTags.begin(), UsedAbiTags.end()); + Parent->EmittedAbiTags.insert(Parent->EmittedAbiTags.end(), + EmittedAbiTags.begin(), + EmittedAbiTags.end()); + } + LinkHead = Parent; + } + + void writeSortedUniqueAbiTags(raw_ostream &Out, const AbiTagList &AbiTags) { + for (const auto &Tag : AbiTags) { + EmittedAbiTags.push_back(Tag); + Out << "B"; + Out << Tag.size(); + Out << Tag; + } + } + }; + + AbiTagState *AbiTags = nullptr; + AbiTagState AbiTagsRoot; + llvm::DenseMap<uintptr_t, unsigned> Substitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } public: CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, - const NamedDecl *D = nullptr) - : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0), - SeqID(0) { + const NamedDecl *D = nullptr, bool NullOut_ = false) + : Context(C), Out(Out_), NullOut(NullOut_), Structor(getStructor(D)), + StructorType(0), SeqID(0), AbiTagsRoot(AbiTags) { // These can't be mangled without a ctor type or dtor type. assert(!D || (!isa<CXXDestructorDecl>(D) && !isa<CXXConstructorDecl>(D))); @@ -277,11 +396,21 @@ public: CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const CXXConstructorDecl *D, CXXCtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), - SeqID(0) { } + SeqID(0), AbiTagsRoot(AbiTags) { } CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), - SeqID(0) { } + SeqID(0), AbiTagsRoot(AbiTags) { } + + CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_) + : Context(Outer.Context), Out(Out_), NullOut(false), + Structor(Outer.Structor), StructorType(Outer.StructorType), + SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {} + + CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_) + : Context(Outer.Context), Out(Out_), NullOut(true), + Structor(Outer.Structor), StructorType(Outer.StructorType), + SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {} #if MANGLE_CHECKER ~CXXNameMangler() { @@ -296,6 +425,9 @@ public: #endif raw_ostream &getStream() { return Out; } + void disableDerivedAbiTags() { DisableDerivedAbiTags = true; } + static bool shouldHaveAbiTags(ItaniumMangleContextImpl &C, const VarDecl *VD); + void mangle(const NamedDecl *D); void mangleCallOffset(int64_t NonVirtual, int64_t Virtual); void mangleNumber(const llvm::APSInt &I); @@ -314,7 +446,6 @@ private: bool mangleSubstitution(TemplateName Template); bool mangleSubstitution(uintptr_t Ptr); - void mangleExistingSubstitution(QualType type); void mangleExistingSubstitution(TemplateName name); bool mangleStandardSubstitution(const NamedDecl *ND); @@ -334,23 +465,37 @@ private: DeclarationName name, unsigned KnownArity = UnknownArity); - void mangleName(const TemplateDecl *TD, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs); - void mangleUnqualifiedName(const NamedDecl *ND) { - mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity); + void mangleFunctionEncodingBareType(const FunctionDecl *FD); + + void mangleNameWithAbiTags(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags); + void mangleTemplateName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); + void mangleUnqualifiedName(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags) { + mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity, + AdditionalAbiTags); } void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name, - unsigned KnownArity); - void mangleUnscopedName(const NamedDecl *ND); - void mangleUnscopedTemplateName(const TemplateDecl *ND); - void mangleUnscopedTemplateName(TemplateName); + unsigned KnownArity, + const AbiTagList *AdditionalAbiTags); + void mangleUnscopedName(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags); + void mangleUnscopedTemplateName(const TemplateDecl *ND, + const AbiTagList *AdditionalAbiTags); + void mangleUnscopedTemplateName(TemplateName, + const AbiTagList *AdditionalAbiTags); void mangleSourceName(const IdentifierInfo *II); - void mangleLocalName(const Decl *D); + void mangleSourceNameWithAbiTags( + const NamedDecl *ND, const AbiTagList *AdditionalAbiTags = nullptr); + void mangleLocalName(const Decl *D, + const AbiTagList *AdditionalAbiTags); void mangleBlockForPrefix(const BlockDecl *Block); void mangleUnqualifiedBlock(const BlockDecl *Block); void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, + const AbiTagList *AdditionalAbiTags, bool NoFunction=false); void mangleNestedName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, @@ -364,6 +509,7 @@ private: StringRef Prefix = ""); void mangleOperatorName(DeclarationName Name, unsigned Arity); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); + void mangleVendorQualifier(StringRef qualifier); void mangleQualifiers(Qualifiers Quals); void mangleRefQualifier(RefQualifierKind RefQualifier); @@ -377,7 +523,10 @@ private: void mangleType(const TagType*); void mangleType(TemplateName); - void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType, + static StringRef getCallingConvQualifierName(CallingConv CC); + void mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo info); + void mangleExtFunctionInfo(const FunctionType *T); + void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType, const FunctionDecl *FD = nullptr); void mangleNeonVectorType(const VectorType *T); void mangleAArch64NeonVectorType(const VectorType *T); @@ -392,7 +541,7 @@ private: void mangleCastExpression(const Expr *E, StringRef CastEncoding); void mangleInitListElements(const InitListExpr *InitList); void mangleExpression(const Expr *E, unsigned Arity = UnknownArity); - void mangleCXXCtorType(CXXCtorType T); + void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom); void mangleCXXDtorType(CXXDtorType T); void mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs, @@ -405,6 +554,14 @@ private: void mangleTemplateParameter(unsigned Index); void mangleFunctionParam(const ParmVarDecl *parm); + + void writeAbiTags(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags); + + // Returns sorted unique list of ABI tags. + AbiTagList makeFunctionReturnTypeTags(const FunctionDecl *FD); + // Returns sorted unique list of ABI tags. + AbiTagList makeVariableTypeTags(const VarDecl *VD); }; } @@ -448,6 +605,7 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage && + !CXXNameMangler::shouldHaveAbiTags(*this, VD) && !isa<VarTemplateSpecializationDecl>(D)) return false; } @@ -455,6 +613,18 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { return true; } +void CXXNameMangler::writeAbiTags(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags) { + assert(AbiTags && "require AbiTagState"); + AbiTags->write(Out, ND, DisableDerivedAbiTags ? nullptr : AdditionalAbiTags); +} + +void CXXNameMangler::mangleSourceNameWithAbiTags( + const NamedDecl *ND, const AbiTagList *AdditionalAbiTags) { + mangleSourceName(ND->getIdentifier()); + writeAbiTags(ND, AdditionalAbiTags); +} + void CXXNameMangler::mangle(const NamedDecl *D) { // <mangled-name> ::= _Z <encoding> // ::= <data name> @@ -472,12 +642,52 @@ void CXXNameMangler::mangle(const NamedDecl *D) { void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { // <encoding> ::= <function name> <bare-function-type> - mangleName(FD); // Don't mangle in the type if this isn't a decl we should typically mangle. - if (!Context.shouldMangleDeclName(FD)) + if (!Context.shouldMangleDeclName(FD)) { + mangleName(FD); + return; + } + + AbiTagList ReturnTypeAbiTags = makeFunctionReturnTypeTags(FD); + if (ReturnTypeAbiTags.empty()) { + // There are no tags for return type, the simplest case. + mangleName(FD); + mangleFunctionEncodingBareType(FD); return; + } + // Mangle function name and encoding to temporary buffer. + // We have to output name and encoding to the same mangler to get the same + // substitution as it will be in final mangling. + SmallString<256> FunctionEncodingBuf; + llvm::raw_svector_ostream FunctionEncodingStream(FunctionEncodingBuf); + CXXNameMangler FunctionEncodingMangler(*this, FunctionEncodingStream); + // Output name of the function. + FunctionEncodingMangler.disableDerivedAbiTags(); + FunctionEncodingMangler.mangleNameWithAbiTags(FD, nullptr); + + // Remember length of the function name in the buffer. + size_t EncodingPositionStart = FunctionEncodingStream.str().size(); + FunctionEncodingMangler.mangleFunctionEncodingBareType(FD); + + // Get tags from return type that are not present in function name or + // encoding. + const AbiTagList &UsedAbiTags = + FunctionEncodingMangler.AbiTagsRoot.getSortedUniqueUsedAbiTags(); + AbiTagList AdditionalAbiTags(ReturnTypeAbiTags.size()); + AdditionalAbiTags.erase( + std::set_difference(ReturnTypeAbiTags.begin(), ReturnTypeAbiTags.end(), + UsedAbiTags.begin(), UsedAbiTags.end(), + AdditionalAbiTags.begin()), + AdditionalAbiTags.end()); + + // Output name with implicit tags and function encoding from temporary buffer. + mangleNameWithAbiTags(FD, &AdditionalAbiTags); + Out << FunctionEncodingStream.str().substr(EncodingPositionStart); +} + +void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { if (FD->hasAttr<EnableIfAttr>()) { FunctionTypeDepthState Saved = FunctionTypeDepth.push(); Out << "Ua9enable_ifI"; @@ -497,6 +707,12 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { FunctionTypeDepth.pop(Saved); } + // When mangling an inheriting constructor, the bare function type used is + // that of the inherited constructor. + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) + if (auto Inherited = CD->getInheritedConstructor()) + FD = Inherited.getConstructor(); + // Whether the mangling of a function type includes the return type depends on // the context and the nature of the function. The rules for deciding whether // the return type is included are: @@ -523,7 +739,7 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { FD = PrimaryTemplate->getTemplatedDecl(); } - mangleBareFunctionType(FD->getType()->getAs<FunctionType>(), + mangleBareFunctionType(FD->getType()->castAs<FunctionProtoType>(), MangleReturnType, FD); } @@ -557,7 +773,7 @@ static bool isStdNamespace(const DeclContext *DC) { static const TemplateDecl * isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { // Check if we have a function template. - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){ + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { if (const TemplateDecl *TD = FD->getPrimaryTemplate()) { TemplateArgs = FD->getTemplateSpecializationArgs(); return TD; @@ -582,6 +798,40 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { } void CXXNameMangler::mangleName(const NamedDecl *ND) { + if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) { + // Variables should have implicit tags from its type. + AbiTagList VariableTypeAbiTags = makeVariableTypeTags(VD); + if (VariableTypeAbiTags.empty()) { + // Simple case no variable type tags. + mangleNameWithAbiTags(VD, nullptr); + return; + } + + // Mangle variable name to null stream to collect tags. + llvm::raw_null_ostream NullOutStream; + CXXNameMangler VariableNameMangler(*this, NullOutStream); + VariableNameMangler.disableDerivedAbiTags(); + VariableNameMangler.mangleNameWithAbiTags(VD, nullptr); + + // Get tags from variable type that are not present in its name. + const AbiTagList &UsedAbiTags = + VariableNameMangler.AbiTagsRoot.getSortedUniqueUsedAbiTags(); + AbiTagList AdditionalAbiTags(VariableTypeAbiTags.size()); + AdditionalAbiTags.erase( + std::set_difference(VariableTypeAbiTags.begin(), + VariableTypeAbiTags.end(), UsedAbiTags.begin(), + UsedAbiTags.end(), AdditionalAbiTags.begin()), + AdditionalAbiTags.end()); + + // Output name with implicit tags. + mangleNameWithAbiTags(VD, &AdditionalAbiTags); + } else { + mangleNameWithAbiTags(ND, nullptr); + } +} + +void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags) { // <name> ::= <nested-name> // ::= <unscoped-name> // ::= <unscoped-template-name> <template-args> @@ -597,7 +847,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { - mangleLocalName(ND); + mangleLocalName(ND, AdditionalAbiTags); return; } @@ -607,76 +857,88 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { - mangleUnscopedTemplateName(TD); + mangleUnscopedTemplateName(TD, AdditionalAbiTags); mangleTemplateArgs(*TemplateArgs); return; } - mangleUnscopedName(ND); + mangleUnscopedName(ND, AdditionalAbiTags); return; } if (isLocalContainerContext(DC)) { - mangleLocalName(ND); + mangleLocalName(ND, AdditionalAbiTags); return; } - mangleNestedName(ND, DC); + mangleNestedName(ND, DC, AdditionalAbiTags); } -void CXXNameMangler::mangleName(const TemplateDecl *TD, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs) { + +void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD)); if (DC->isTranslationUnit() || isStdNamespace(DC)) { - mangleUnscopedTemplateName(TD); + mangleUnscopedTemplateName(TD, nullptr); mangleTemplateArgs(TemplateArgs, NumTemplateArgs); } else { mangleNestedName(TD, TemplateArgs, NumTemplateArgs); } } -void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) { +void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND, + const AbiTagList *AdditionalAbiTags) { // <unscoped-name> ::= <unqualified-name> // ::= St <unqualified-name> # ::std:: if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND)))) Out << "St"; - mangleUnqualifiedName(ND); + mangleUnqualifiedName(ND, AdditionalAbiTags); } -void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) { +void CXXNameMangler::mangleUnscopedTemplateName( + const TemplateDecl *ND, const AbiTagList *AdditionalAbiTags) { // <unscoped-template-name> ::= <unscoped-name> // ::= <substitution> if (mangleSubstitution(ND)) return; // <template-template-param> ::= <template-param> - if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) + if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) { + assert(!AdditionalAbiTags && + "template template param cannot have abi tags"); mangleTemplateParameter(TTP->getIndex()); - else - mangleUnscopedName(ND->getTemplatedDecl()); + } else if (isa<BuiltinTemplateDecl>(ND)) { + mangleUnscopedName(ND, AdditionalAbiTags); + } else { + mangleUnscopedName(ND->getTemplatedDecl(), AdditionalAbiTags); + } addSubstitution(ND); } -void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) { +void CXXNameMangler::mangleUnscopedTemplateName( + TemplateName Template, const AbiTagList *AdditionalAbiTags) { // <unscoped-template-name> ::= <unscoped-name> // ::= <substitution> if (TemplateDecl *TD = Template.getAsTemplateDecl()) - return mangleUnscopedTemplateName(TD); + return mangleUnscopedTemplateName(TD, AdditionalAbiTags); if (mangleSubstitution(Template)) return; + assert(!AdditionalAbiTags && + "dependent template name cannot have abi tags"); + DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); assert(Dependent && "Not a dependent template name?"); if (const IdentifierInfo *Id = Dependent->getIdentifier()) mangleSourceName(Id); else mangleOperatorName(Dependent->getOperator(), UnknownArity); - + addSubstitution(Template); } @@ -834,7 +1096,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, /*recursive*/ true); else Out << "sr"; - mangleSourceName(qualifier->getAsNamespace()->getIdentifier()); + mangleSourceNameWithAbiTags(qualifier->getAsNamespace()); break; case NestedNameSpecifier::NamespaceAlias: if (qualifier->getPrefix()) @@ -842,7 +1104,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, /*recursive*/ true); else Out << "sr"; - mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier()); + mangleSourceNameWithAbiTags(qualifier->getAsNamespaceAlias()); break; case NestedNameSpecifier::TypeSpec: @@ -877,6 +1139,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, Out << "sr"; mangleSourceName(qualifier->getAsIdentifier()); + // An Identifier has no type information, so we can't emit abi tags for it. break; } @@ -922,7 +1185,8 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier, void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name, - unsigned KnownArity) { + unsigned KnownArity, + const AbiTagList *AdditionalAbiTags) { unsigned Arity = KnownArity; // <unqualified-name> ::= <operator-name> // ::= <ctor-dtor-name> @@ -941,6 +1205,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, Out << 'L'; mangleSourceName(II); + writeAbiTags(ND, AdditionalAbiTags); break; } @@ -980,6 +1245,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, assert(FD->getIdentifier() && "Data member name isn't an identifier!"); mangleSourceName(FD->getIdentifier()); + // Not emitting abi tags: internal name anyway. break; } @@ -1000,6 +1266,10 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, assert(D->getDeclName().getAsIdentifierInfo() && "Typedef was not named!"); mangleSourceName(D->getDeclName().getAsIdentifierInfo()); + assert(!AdditionalAbiTags && "Type cannot have additional abi tags"); + // Explicit abi tags are still possible; take from underlying type, not + // from typedef. + writeAbiTags(TD, nullptr); break; } @@ -1009,6 +1279,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // <lambda-sig> ::= <parameter-type>+ # Parameter types or 'v' for 'void'. if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { if (Record->isLambda() && Record->getLambdaManglingNumber()) { + assert(!AdditionalAbiTags && + "Lambda type cannot have additional abi tags"); mangleLambda(Record); break; } @@ -1020,11 +1292,13 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, if (UnnamedMangle > 1) Out << UnnamedMangle - 2; Out << '_'; + writeAbiTags(TD, AdditionalAbiTags); break; } - // Get a unique id for the anonymous struct. - unsigned AnonStructId = Context.getAnonymousStructId(TD); + // Get a unique id for the anonymous struct. If it is not a real output + // ID doesn't matter so use fake one. + unsigned AnonStructId = NullOut ? 0 : Context.getAnonymousStructId(TD); // Mangle it as a source name in the form // [n] $_<id> @@ -1043,16 +1317,33 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, case DeclarationName::ObjCMultiArgSelector: llvm_unreachable("Can't mangle Objective-C selector names here!"); - case DeclarationName::CXXConstructorName: + case DeclarationName::CXXConstructorName: { + const CXXRecordDecl *InheritedFrom = nullptr; + const TemplateArgumentList *InheritedTemplateArgs = nullptr; + if (auto Inherited = + cast<CXXConstructorDecl>(ND)->getInheritedConstructor()) { + InheritedFrom = Inherited.getConstructor()->getParent(); + InheritedTemplateArgs = + Inherited.getConstructor()->getTemplateSpecializationArgs(); + } + if (ND == Structor) // If the named decl is the C++ constructor we're mangling, use the type // we were given. - mangleCXXCtorType(static_cast<CXXCtorType>(StructorType)); + mangleCXXCtorType(static_cast<CXXCtorType>(StructorType), InheritedFrom); else // Otherwise, use the complete constructor name. This is relevant if a // class with a constructor is declared within a constructor. - mangleCXXCtorType(Ctor_Complete); + mangleCXXCtorType(Ctor_Complete, InheritedFrom); + + // FIXME: The template arguments are part of the enclosing prefix or + // nested-name, but it's more convenient to mangle them here. + if (InheritedTemplateArgs) + mangleTemplateArgs(*InheritedTemplateArgs); + + writeAbiTags(ND, AdditionalAbiTags); break; + } case DeclarationName::CXXDestructorName: if (ND == Structor) @@ -1063,6 +1354,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // Otherwise, use the complete destructor name. This is relevant if a // class with a destructor is declared within a destructor. mangleCXXDtorType(Dtor_Complete); + writeAbiTags(ND, AdditionalAbiTags); break; case DeclarationName::CXXOperatorName: @@ -1078,6 +1370,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXLiteralOperatorName: mangleOperatorName(Name, Arity); + writeAbiTags(ND, AdditionalAbiTags); break; case DeclarationName::CXXUsingDirective: @@ -1094,6 +1387,7 @@ void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { void CXXNameMangler::mangleNestedName(const NamedDecl *ND, const DeclContext *DC, + const AbiTagList *AdditionalAbiTags, bool NoFunction) { // <nested-name> // ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E @@ -1119,7 +1413,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, } else { manglePrefix(DC, NoFunction); - mangleUnqualifiedName(ND); + mangleUnqualifiedName(ND, AdditionalAbiTags); } Out << 'E'; @@ -1137,7 +1431,8 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, Out << 'E'; } -void CXXNameMangler::mangleLocalName(const Decl *D) { +void CXXNameMangler::mangleLocalName(const Decl *D, + const AbiTagList *AdditionalAbiTags) { // <local-name> := Z <function encoding> E <entity name> [<discriminator>] // := Z <function encoding> E s [<discriminator>] // <local-name> := Z <function encoding> E d [ <parameter number> ] @@ -1149,15 +1444,26 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { Out << 'Z'; - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) - mangleObjCMethodName(MD); - else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) - mangleBlockForPrefix(BD); - else - mangleFunctionEncoding(cast<FunctionDecl>(DC)); + { + AbiTagState LocalAbiTags(AbiTags); + + if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) + mangleObjCMethodName(MD); + else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) + mangleBlockForPrefix(BD); + else + mangleFunctionEncoding(cast<FunctionDecl>(DC)); + + // Implicit ABI tags (from namespace) are not available in the following + // entity; reset to actually emitted tags, which are available. + LocalAbiTags.setUsedAbiTags(LocalAbiTags.getEmittedAbiTags()); + } Out << 'E'; + // GCC 5.3.0 doesn't emit derived ABI tags for local names but that seems to + // be a bug that is fixed in trunk. + if (RD) { // The parameter number is omitted for the last parameter, 0 for the // second-to-last parameter, 1 for the third-to-last parameter, etc. The @@ -1182,13 +1488,15 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { // Mangle the name relative to the closest enclosing function. // equality ok because RD derived from ND above if (D == RD) { - mangleUnqualifiedName(RD); + mangleUnqualifiedName(RD, AdditionalAbiTags); } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/); + assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); mangleUnqualifiedBlock(BD); } else { const NamedDecl *ND = cast<NamedDecl>(D); - mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/); + mangleNestedName(ND, getEffectiveDeclContext(ND), AdditionalAbiTags, + true /*NoFunction*/); } } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { // Mangle a block in a default parameter; see above explanation for @@ -1205,9 +1513,10 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { } } + assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); mangleUnqualifiedBlock(BD); } else { - mangleUnqualifiedName(cast<NamedDecl>(D)); + mangleUnqualifiedName(cast<NamedDecl>(D), AdditionalAbiTags); } if (const NamedDecl *ND = dyn_cast<NamedDecl>(RD ? RD : D)) { @@ -1223,12 +1532,12 @@ void CXXNameMangler::mangleLocalName(const Decl *D) { void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) { if (GetLocalClassDecl(Block)) { - mangleLocalName(Block); + mangleLocalName(Block, /* AdditionalAbiTags */ nullptr); return; } const DeclContext *DC = getEffectiveDeclContext(Block); if (isLocalContainerContext(DC)) { - mangleLocalName(Block); + mangleLocalName(Block, /* AdditionalAbiTags */ nullptr); return; } manglePrefix(getEffectiveDeclContext(Block)); @@ -1239,10 +1548,10 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { if (Decl *Context = Block->getBlockManglingContextDecl()) { if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && Context->getDeclContext()->isRecord()) { - if (const IdentifierInfo *Name - = cast<NamedDecl>(Context)->getIdentifier()) { - mangleSourceName(Name); - Out << 'M'; + const auto *ND = cast<NamedDecl>(Context); + if (ND->getIdentifier()) { + mangleSourceNameWithAbiTags(ND); + Out << 'M'; } } } @@ -1275,7 +1584,7 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { if (const IdentifierInfo *Name = cast<NamedDecl>(Context)->getIdentifier()) { mangleSourceName(Name); - Out << 'M'; + Out << 'M'; } } } @@ -1362,7 +1671,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { mangleTemplateArgs(*TemplateArgs); } else { manglePrefix(getEffectiveDeclContext(ND), NoFunction); - mangleUnqualifiedName(ND); + mangleUnqualifiedName(ND, nullptr); } addSubstitution(ND); @@ -1377,19 +1686,19 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName()) manglePrefix(Qualified->getQualifier()); - + if (OverloadedTemplateStorage *Overloaded = Template.getAsOverloadedTemplate()) { mangleUnqualifiedName(nullptr, (*Overloaded->begin())->getDeclName(), - UnknownArity); + UnknownArity, nullptr); return; } - + DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); assert(Dependent && "Unknown template name kind?"); if (NestedNameSpecifier *Qualifier = Dependent->getQualifier()) manglePrefix(Qualifier); - mangleUnscopedTemplateName(Template); + mangleUnscopedTemplateName(Template, /* AdditionalAbiTags */ nullptr); } void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND, @@ -1408,7 +1717,10 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND, mangleTemplateParameter(TTP->getIndex()); } else { manglePrefix(getEffectiveDeclContext(ND), NoFunction); - mangleUnqualifiedName(ND->getTemplatedDecl()); + if (isa<BuiltinTemplateDecl>(ND)) + mangleUnqualifiedName(ND, nullptr); + else + mangleUnqualifiedName(ND->getTemplatedDecl(), nullptr); } addSubstitution(ND); @@ -1543,17 +1855,17 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, return true; case Type::Typedef: - mangleSourceName(cast<TypedefType>(Ty)->getDecl()->getIdentifier()); + mangleSourceNameWithAbiTags(cast<TypedefType>(Ty)->getDecl()); break; case Type::UnresolvedUsing: - mangleSourceName( - cast<UnresolvedUsingType>(Ty)->getDecl()->getIdentifier()); + mangleSourceNameWithAbiTags( + cast<UnresolvedUsingType>(Ty)->getDecl()); break; case Type::Enum: case Type::Record: - mangleSourceName(cast<TagType>(Ty)->getDecl()->getIdentifier()); + mangleSourceNameWithAbiTags(cast<TagType>(Ty)->getDecl()); break; case Type::TemplateSpecialization: { @@ -1571,7 +1883,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, if (isa<TemplateTemplateParmDecl>(TD)) goto unresolvedType; - mangleSourceName(TD->getIdentifier()); + mangleSourceNameWithAbiTags(TD); break; } @@ -1601,8 +1913,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, } case Type::InjectedClassName: - mangleSourceName( - cast<InjectedClassNameType>(Ty)->getDecl()->getIdentifier()); + mangleSourceNameWithAbiTags( + cast<InjectedClassNameType>(Ty)->getDecl()); break; case Type::DependentName: @@ -1653,8 +1965,6 @@ void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned Arity) { } } - - void CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { switch (OO) { @@ -1767,14 +2077,9 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { } void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { - // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const - if (Quals.hasRestrict()) - Out << 'r'; - if (Quals.hasVolatile()) - Out << 'V'; - if (Quals.hasConst()) - Out << 'K'; + // Vendor qualifiers come first. + // Address space qualifiers start with an ordinary letter. if (Quals.hasAddressSpace()) { // Address space extension: // @@ -1788,7 +2093,7 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { if (Context.getASTContext().addressSpaceMapManglingFor(AS)) { // <target-addrspace> ::= "AS" <address-space-number> unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS); - ASString = "AS" + llvm::utostr_32(TargetAS); + ASString = "AS" + llvm::utostr(TargetAS); } else { switch (AS) { default: llvm_unreachable("Not a language specific address space"); @@ -1802,10 +2107,10 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { case LangAS::cuda_shared: ASString = "CUshared"; break; } } - Out << 'U' << ASString.size() << ASString; + mangleVendorQualifier(ASString); } - - StringRef LifetimeName; + + // The ARC ownership qualifiers start with underscores. switch (Quals.getObjCLifetime()) { // Objective-C ARC Extension: // @@ -1816,15 +2121,15 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { break; case Qualifiers::OCL_Weak: - LifetimeName = "__weak"; + mangleVendorQualifier("__weak"); break; case Qualifiers::OCL_Strong: - LifetimeName = "__strong"; + mangleVendorQualifier("__strong"); break; case Qualifiers::OCL_Autoreleasing: - LifetimeName = "__autoreleasing"; + mangleVendorQualifier("__autoreleasing"); break; case Qualifiers::OCL_ExplicitNone: @@ -1837,8 +2142,18 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { // in any type signatures that need to be mangled. break; } - if (!LifetimeName.empty()) - Out << 'U' << LifetimeName.size() << LifetimeName; + + // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const + if (Quals.hasRestrict()) + Out << 'r'; + if (Quals.hasVolatile()) + Out << 'V'; + if (Quals.hasConst()) + Out << 'K'; +} + +void CXXNameMangler::mangleVendorQualifier(StringRef name) { + Out << 'U' << name.size() << name; } void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) { @@ -1981,7 +2296,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // ::= f # float // ::= d # double // ::= e # long double, __float80 - // UNSUPPORTED: ::= g # __float128 + // ::= g # __float128 // UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits) // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits) // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits) @@ -1990,6 +2305,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // ::= Ds # char16_t // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) // ::= u <source-name> # vendor extended type + std::string type_name; switch (T->getKind()) { case BuiltinType::Void: Out << 'v'; @@ -2061,6 +2377,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { ? 'g' : 'e'); break; + case BuiltinType::Float128: + if (getASTContext().getTargetInfo().useFloat128ManglingForLongDouble()) + Out << "U10__float128"; // Match the GCC mangling + else + Out << 'g'; + break; case BuiltinType::NullPtr: Out << "Dn"; break; @@ -2070,7 +2392,9 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Id: #include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: - llvm_unreachable("mangling a placeholder type"); + if (!NullOut) + llvm_unreachable("mangling a placeholder type"); + break; case BuiltinType::ObjCId: Out << "11objc_object"; break; @@ -2080,42 +2404,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { 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"; +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: \ + type_name = "ocl_" #ImgType "_" #Suffix; \ + Out << type_name.size() << type_name; \ break; +#include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: Out << "11ocl_sampler"; break; @@ -2137,10 +2431,80 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { } } +StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { + switch (CC) { + case CC_C: + return ""; + + case CC_X86StdCall: + case CC_X86FastCall: + case CC_X86ThisCall: + case CC_X86VectorCall: + case CC_X86Pascal: + case CC_X86_64Win64: + case CC_X86_64SysV: + case CC_AAPCS: + case CC_AAPCS_VFP: + case CC_IntelOclBicc: + case CC_SpirFunction: + case CC_OpenCLKernel: + case CC_PreserveMost: + case CC_PreserveAll: + // FIXME: we should be mangling all of the above. + return ""; + + case CC_Swift: + return "swiftcall"; + } + llvm_unreachable("bad calling convention"); +} + +void CXXNameMangler::mangleExtFunctionInfo(const FunctionType *T) { + // Fast path. + if (T->getExtInfo() == FunctionType::ExtInfo()) + return; + + // Vendor-specific qualifiers are emitted in reverse alphabetical order. + // This will get more complicated in the future if we mangle other + // things here; but for now, since we mangle ns_returns_retained as + // a qualifier on the result type, we can get away with this: + StringRef CCQualifier = getCallingConvQualifierName(T->getExtInfo().getCC()); + if (!CCQualifier.empty()) + mangleVendorQualifier(CCQualifier); + + // FIXME: regparm + // FIXME: noreturn +} + +void +CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) { + // Vendor-specific qualifiers are emitted in reverse alphabetical order. + + // Note that these are *not* substitution candidates. Demanglers might + // have trouble with this if the parameter type is fully substituted. + + switch (PI.getABI()) { + case ParameterABI::Ordinary: + break; + + // All of these start with "swift", so they come before "ns_consumed". + case ParameterABI::SwiftContext: + case ParameterABI::SwiftErrorResult: + case ParameterABI::SwiftIndirectResult: + mangleVendorQualifier(getParameterABISpelling(PI.getABI())); + break; + } + + if (PI.isConsumed()) + mangleVendorQualifier("ns_consumed"); +} + // <type> ::= <function-type> // <function-type> ::= [<CV-qualifiers>] F [Y] // <bare-function-type> [<ref-qualifier>] E void CXXNameMangler::mangleType(const FunctionProtoType *T) { + mangleExtFunctionInfo(T); + // Mangle CV-qualifiers, if present. These are 'this' qualifiers, // e.g. "const" in "int (A::*)() const". mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals())); @@ -2173,12 +2537,9 @@ void CXXNameMangler::mangleType(const FunctionNoProtoType *T) { Out << 'E'; } -void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, +void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto, bool MangleReturnType, const FunctionDecl *FD) { - // We should never be mangling something without a prototype. - const FunctionProtoType *Proto = cast<FunctionProtoType>(T); - // Record that we're in a function type. See mangleFunctionParam // for details on what we're trying to achieve here. FunctionTypeDepthState saved = FunctionTypeDepth.push(); @@ -2186,7 +2547,20 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, // <bare-function-type> ::= <signature type>+ if (MangleReturnType) { FunctionTypeDepth.enterResultType(); - mangleType(Proto->getReturnType()); + + // Mangle ns_returns_retained as an order-sensitive qualifier here. + if (Proto->getExtInfo().getProducesResult() && FD == nullptr) + mangleVendorQualifier("ns_returns_retained"); + + // Mangle the return type without any direct ARC ownership qualifiers. + QualType ReturnTy = Proto->getReturnType(); + if (ReturnTy.getObjCLifetime()) { + auto SplitReturnTy = ReturnTy.split(); + SplitReturnTy.Quals.removeObjCLifetime(); + ReturnTy = getASTContext().getQualifiedType(SplitReturnTy); + } + mangleType(ReturnTy); + FunctionTypeDepth.leaveResultType(); } @@ -2200,7 +2574,13 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, assert(!FD || FD->getNumParams() == Proto->getNumParams()); for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) { - const auto &ParamTy = Proto->getParamType(I); + // Mangle extended parameter info as order-sensitive qualifiers here. + if (Proto->hasExtParameterInfos() && FD == nullptr) { + mangleExtParameterInfo(Proto->getExtParameterInfo(I)); + } + + // Mangle the type. + QualType ParamTy = Proto->getParamType(I); mangleType(Context.getASTContext().getSignatureParameterType(ParamTy)); if (FD) { @@ -2546,7 +2926,7 @@ void CXXNameMangler::mangleType(const InjectedClassNameType *T) { void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) { - mangleName(TD, T->getArgs(), T->getNumArgs()); + mangleTemplateName(TD, T->getArgs(), T->getNumArgs()); } else { if (mangleSubstitution(QualType(T, 0))) return; @@ -2662,7 +3042,7 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) { } } - mangleType(T->getUnderlyingType()); + mangleType(T->getBaseType()); } void CXXNameMangler::mangleType(const AutoType *T) { @@ -2836,6 +3216,7 @@ recurse: case Expr::MSPropertySubscriptExprClass: case Expr::TypoExprClass: // This should no longer exist in the AST by now. case Expr::OMPArraySectionExprClass: + case Expr::CXXInheritedCtorInitExprClass: llvm_unreachable("unexpected statement kind"); // FIXME: invent manglings for all these. @@ -2858,6 +3239,7 @@ recurse: case Expr::ObjCDictionaryLiteralClass: case Expr::ObjCSubscriptRefExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: + case Expr::ObjCAvailabilityCheckExprClass: case Expr::OffsetOfExprClass: case Expr::PredefinedExprClass: case Expr::ShuffleVectorExprClass: @@ -2872,12 +3254,14 @@ recurse: case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: { - // As bad as this diagnostic is, it's better than crashing. - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot yet mangle expression type %0"); - Diags.Report(E->getExprLoc(), DiagID) - << E->getStmtClassName() << E->getSourceRange(); + if (!NullOut) { + // As bad as this diagnostic is, it's better than crashing. + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot yet mangle expression type %0"); + Diags.Report(E->getExprLoc(), DiagID) + << E->getStmtClassName() << E->getSourceRange(); + } break; } @@ -3615,25 +3999,33 @@ void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) { Out << '_'; } -void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) { +void CXXNameMangler::mangleCXXCtorType(CXXCtorType T, + const CXXRecordDecl *InheritedFrom) { // <ctor-dtor-name> ::= C1 # complete object constructor // ::= C2 # base object constructor + // ::= CI1 <type> # complete inheriting constructor + // ::= CI2 <type> # base inheriting constructor // // In addition, C5 is a comdat name with C1 and C2 in it. + Out << 'C'; + if (InheritedFrom) + Out << 'I'; switch (T) { case Ctor_Complete: - Out << "C1"; + Out << '1'; break; case Ctor_Base: - Out << "C2"; + Out << '2'; break; case Ctor_Comdat: - Out << "C5"; + Out << '5'; break; case Ctor_DefaultClosure: case Ctor_CopyingClosure: llvm_unreachable("closure constructors don't exist for the Itanium ABI!"); } + if (InheritedFrom) + mangleName(InheritedFrom); } void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { @@ -3745,7 +4137,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) { Out << 'L'; // References to external entities use the mangled name; if the name would - // not normally be manged then mangle it as unqualified. + // not normally be mangled then mangle it as unqualified. mangle(D); Out << 'E'; @@ -3801,12 +4193,6 @@ void CXXNameMangler::mangleSeqID(unsigned SeqID) { Out << '_'; } -void CXXNameMangler::mangleExistingSubstitution(QualType type) { - bool result = mangleSubstitution(type); - assert(result && "no existing substitution for type"); - (void) result; -} - void CXXNameMangler::mangleExistingSubstitution(TemplateName tname) { bool result = mangleSubstitution(tname); assert(result && "no existing substitution for template name"); @@ -4020,6 +4406,48 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) { Substitutions[Ptr] = SeqID++; } +CXXNameMangler::AbiTagList +CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) { + // When derived abi tags are disabled there is no need to make any list. + if (DisableDerivedAbiTags) + return AbiTagList(); + + llvm::raw_null_ostream NullOutStream; + CXXNameMangler TrackReturnTypeTags(*this, NullOutStream); + TrackReturnTypeTags.disableDerivedAbiTags(); + + const FunctionProtoType *Proto = + cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>()); + TrackReturnTypeTags.FunctionTypeDepth.enterResultType(); + TrackReturnTypeTags.mangleType(Proto->getReturnType()); + TrackReturnTypeTags.FunctionTypeDepth.leaveResultType(); + + return TrackReturnTypeTags.AbiTagsRoot.getSortedUniqueUsedAbiTags(); +} + +CXXNameMangler::AbiTagList +CXXNameMangler::makeVariableTypeTags(const VarDecl *VD) { + // When derived abi tags are disabled there is no need to make any list. + if (DisableDerivedAbiTags) + return AbiTagList(); + + llvm::raw_null_ostream NullOutStream; + CXXNameMangler TrackVariableType(*this, NullOutStream); + TrackVariableType.disableDerivedAbiTags(); + + TrackVariableType.mangleType(VD->getType()); + + return TrackVariableType.AbiTagsRoot.getSortedUniqueUsedAbiTags(); +} + +bool CXXNameMangler::shouldHaveAbiTags(ItaniumMangleContextImpl &C, + const VarDecl *VD) { + llvm::raw_null_ostream NullOutStream; + CXXNameMangler TrackAbiTags(C, NullOutStream, nullptr, true); + TrackAbiTags.mangle(VD); + return TrackAbiTags.AbiTagsRoot.getUsedAbiTags().size(); +} + // /// Mangles the name of the declaration D and emits that name to the given @@ -4121,6 +4549,8 @@ void ItaniumMangleContextImpl::mangleStaticGuardVariable(const VarDecl *D, // <special-name> ::= GV <object name> # Guard variable for one-time // # initialization CXXNameMangler Mangler(*this, Out); + // GCC 5.3.0 doesn't emit derived ABI tags for local names but that seems to + // be a bug that is fixed in trunk. Mangler.getStream() << "_ZGV"; Mangler.mangleName(D); } diff --git a/lib/AST/Makefile b/lib/AST/Makefile deleted file mode 100644 index 65383c5552d4..000000000000 --- a/lib/AST/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -##===- clang/lib/AST/Makefile ------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# This implements the AST library for the C-Language front-end. -# -##===----------------------------------------------------------------------===## - -CLANG_LEVEL := ../.. -LIBRARYNAME := clangAST - -include $(CLANG_LEVEL)/Makefile - diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp index 014338f0490f..ee241732e8ad 100644 --- a/lib/AST/Mangle.cpp +++ b/lib/AST/Mangle.cpp @@ -126,9 +126,9 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) { // llvm mangler on ELF is a nop, so we can just avoid adding the \01 // marker. We also avoid adding the marker if this is an alias for an // LLVM intrinsic. - StringRef UserLabelPrefix = - getASTContext().getTargetInfo().getUserLabelPrefix(); - if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm.")) + char GlobalPrefix = + getASTContext().getTargetInfo().getDataLayout().getGlobalPrefix(); + if (GlobalPrefix && !ALA->getLabel().startswith("llvm.")) Out << '\01'; // LLVM IR Marker for __asm("foo") Out << ALA->getLabel(); @@ -177,9 +177,9 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) { ++ArgWords; for (const auto &AT : Proto->param_types()) // Size should be aligned to pointer size. - ArgWords += llvm::RoundUpToAlignment(ASTContext.getTypeSize(AT), - TI.getPointerWidth(0)) / - TI.getPointerWidth(0); + ArgWords += + llvm::alignTo(ASTContext.getTypeSize(AT), TI.getPointerWidth(0)) / + TI.getPointerWidth(0); Out << ((TI.getPointerWidth(0) / 8) * ArgWords); } @@ -254,11 +254,8 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, mangleFunctionBlock(*this, Buffer, BD, Out); } -void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, - raw_ostream &Out) { - SmallString<64> Name; - llvm::raw_svector_ostream OS(Name); - +void MangleContext::mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD, + raw_ostream &OS) { const ObjCContainerDecl *CD = dyn_cast<ObjCContainerDecl>(MD->getDeclContext()); assert (CD && "Missing container decl in GetNameForMethod"); @@ -268,6 +265,13 @@ void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, OS << ' '; MD->getSelector().print(OS); OS << ']'; - +} + +void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, + raw_ostream &Out) { + SmallString<64> Name; + llvm::raw_svector_ostream OS(Name); + + mangleObjCMethodNameWithoutSize(MD, OS); Out << OS.str().size() << OS.str(); } diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp index 6ba31ccf1e37..3ae04538d626 100644 --- a/lib/AST/MicrosoftCXXABI.cpp +++ b/lib/AST/MicrosoftCXXABI.cpp @@ -262,7 +262,7 @@ std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign( Align = Target.getIntAlign(); if (Target.getTriple().isArch64Bit()) - Width = llvm::RoundUpToAlignment(Width, Align); + Width = llvm::alignTo(Width, Align); return std::make_pair(Width, Align); } diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 4a45f9e4051f..351997e02a9d 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -19,6 +19,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -27,13 +28,44 @@ #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/JamCRC.h" +#include "llvm/Support/MD5.h" +#include "llvm/Support/MathExtras.h" using namespace clang; namespace { +struct msvc_hashing_ostream : public llvm::raw_svector_ostream { + raw_ostream &OS; + llvm::SmallString<64> Buffer; + + msvc_hashing_ostream(raw_ostream &OS) + : llvm::raw_svector_ostream(Buffer), OS(OS) {} + ~msvc_hashing_ostream() override { + StringRef MangledName = str(); + bool StartsWithEscape = MangledName.startswith("\01"); + if (StartsWithEscape) + MangledName = MangledName.drop_front(1); + if (MangledName.size() <= 4096) { + OS << str(); + return; + } + + llvm::MD5 Hasher; + llvm::MD5::MD5Result Hash; + Hasher.update(MangledName); + Hasher.final(Hash); + + SmallString<32> HexString; + llvm::MD5::stringifyResult(Hash, HexString); + + if (StartsWithEscape) + OS << '\01'; + OS << "??@" << HexString << '@'; + } +}; + /// \brief Retrieve the declaration context that should be used when mangling /// the given declaration. static const DeclContext *getEffectiveDeclContext(const Decl *D) { @@ -58,10 +90,11 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { } const DeclContext *DC = D->getDeclContext(); - if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC)) - return getEffectiveDeclContext(CD); + if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC)) { + return getEffectiveDeclContext(cast<Decl>(DC)); + } - return DC; + return DC->getRedeclContext(); } static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { @@ -120,7 +153,8 @@ public: const CXXRecordDecl *DstRD, raw_ostream &Out) override; void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile, - uint32_t NumEntries, raw_ostream &Out) override; + bool IsUnaligned, uint32_t NumEntries, + raw_ostream &Out) override; void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries, raw_ostream &Out) override; void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD, @@ -160,14 +194,17 @@ public: raw_ostream &Out) override; void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override; bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { - // Lambda closure types are already numbered. - if (isLambda(ND)) - return false; - const DeclContext *DC = getEffectiveDeclContext(ND); if (!DC->isFunctionOrMethod()) return false; + // Lambda closure types are already numbered, give out a phony number so + // that they demangle nicely. + if (isLambda(ND)) { + disc = 1; + return true; + } + // Use the canonical number for externally visible decls. if (ND->isExternallyVisible()) { disc = getASTContext().getManglingNumber(ND); @@ -201,7 +238,7 @@ public: } private: - void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode); + void mangleInitFiniStub(const VarDecl *D, char CharCode, raw_ostream &Out); }; /// MicrosoftCXXNameMangler - Manage the mangling of a single name for the @@ -1150,7 +1187,7 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { // 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()); + StringRef Uuid = UE->getUuidStr(); std::string Name = "_GUID_" + Uuid.lower(); std::replace(Name.begin(), Name.end(), '-', '_'); @@ -1410,6 +1447,10 @@ void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals, if (HasRestrict) Out << 'I'; + + if (Quals.hasUnaligned() || + (!PointeeType.isNull() && PointeeType.getLocalQualifiers().hasUnaligned())) + Out << 'F'; } void MicrosoftCXXNameMangler::manglePointerCVQualifiers(Qualifiers Quals) { @@ -1541,6 +1582,8 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, } break; case QMM_Result: + // Presence of __unaligned qualifier shouldn't affect mangling here. + Quals.removeUnaligned(); if ((!IsPointer && Quals) || isa<TagType>(T)) { Out << '?'; mangleQualifiers(Quals, false); @@ -1681,54 +1724,11 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, mangleArtificalTagType(TTK_Struct, "objc_selector"); 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"); +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: \ + Out << "PAUocl_" #ImgType "_" #Suffix "@@"; \ break; +#include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: Out << "PA"; mangleArtificalTagType(TTK_Struct, "ocl_sampler"); @@ -1758,6 +1758,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, Out << "$$T"; break; + case BuiltinType::Float128: case BuiltinType::Half: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID( @@ -1799,9 +1800,12 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, SourceRange Range; if (D) Range = D->getSourceRange(); + bool IsInLambda = false; bool IsStructor = false, HasThisQuals = ForceThisQuals, IsCtorClosure = false; CallingConv CC = T->getCallConv(); if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) { + if (MD->getParent()->isLambda()) + IsInLambda = true; if (MD->isInstance()) HasThisQuals = true; if (isa<CXXDestructorDecl>(MD)) { @@ -1820,7 +1824,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. if (HasThisQuals) { - Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals()); + Qualifiers Quals = Qualifiers::fromCVRUMask(Proto->getTypeQuals()); manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType()); mangleRefQualifier(Proto->getRefQualifier()); mangleQualifiers(Quals, /*IsMember=*/false); @@ -1875,6 +1879,8 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, "shouldn't need to mangle __auto_type!"); mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>"); Out << '@'; + } else if (IsInLambda) { + Out << '@'; } else { if (ResultType->isVoidType()) ResultType = ResultType.getUnqualifiedType(); @@ -2448,7 +2454,8 @@ void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D, getASTContext().getSourceManager(), "Mangling declaration"); - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); return Mangler.mangle(D); } @@ -2548,7 +2555,8 @@ MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, const MicrosoftVTableContext::MethodVFTableLocation &ML = VTContext->getMethodVFTableLocation(GlobalDecl(MD)); - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "\01?"; Mangler.mangleVirtualMemPtrThunk(MD, ML); } @@ -2556,10 +2564,11 @@ MicrosoftMangleContextImpl::mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, void MicrosoftMangleContextImpl::mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); - Out << "\01?"; + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); + Mangler.getStream() << "\01?"; Mangler.mangleName(MD); - mangleThunkThisAdjustment(MD, Thunk.This, Mangler, Out); + mangleThunkThisAdjustment(MD, Thunk.This, Mangler, MHO); if (!Thunk.Return.isEmpty()) assert(Thunk.Method != nullptr && "Thunk info should hold the overridee decl"); @@ -2576,10 +2585,11 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk( // dtors rather than scalar deleting dtors. Just use the vector deleting dtor // mangling manually until we support both deleting dtor types. assert(Type == Dtor_Deleting); - MicrosoftCXXNameMangler Mangler(*this, Out, DD, Type); - Out << "\01??_E"; + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type); + Mangler.getStream() << "\01??_E"; Mangler.mangleName(DD->getParent()); - mangleThunkThisAdjustment(DD, Adjustment, Mangler, Out); + mangleThunkThisAdjustment(DD, Adjustment, Mangler, MHO); Mangler.mangleFunctionType(DD->getType()->castAs<FunctionProtoType>(), DD); } @@ -2590,8 +2600,12 @@ void MicrosoftMangleContextImpl::mangleCXXVFTable( // <cvr-qualifiers> [<name>] @ // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class> // is always '6' for vftables. - MicrosoftCXXNameMangler Mangler(*this, Out); - Mangler.getStream() << "\01??_7"; + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); + if (Derived->hasAttr<DLLImportAttr>()) + Mangler.getStream() << "\01??_S"; + else + Mangler.getStream() << "\01??_7"; Mangler.mangleName(Derived); Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const. for (const CXXRecordDecl *RD : BasePath) @@ -2606,7 +2620,8 @@ void MicrosoftMangleContextImpl::mangleCXXVBTable( // <cvr-qualifiers> [<name>] @ // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class> // is always '7' for vbtables. - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "\01??_8"; Mangler.mangleName(Derived); Mangler.getStream() << "7B"; // '7' for vbtable, 'B' for const. @@ -2616,7 +2631,8 @@ void MicrosoftMangleContextImpl::mangleCXXVBTable( } void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "\01??_R0"; Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); Mangler.getStream() << "@8"; @@ -2631,31 +2647,36 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, void MicrosoftMangleContextImpl::mangleCXXVirtualDisplacementMap( const CXXRecordDecl *SrcRD, const CXXRecordDecl *DstRD, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "\01??_K"; Mangler.mangleName(SrcRD); Mangler.getStream() << "$C"; Mangler.mangleName(DstRD); } -void MicrosoftMangleContextImpl::mangleCXXThrowInfo(QualType T, - bool IsConst, +void MicrosoftMangleContextImpl::mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile, + bool IsUnaligned, uint32_t NumEntries, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "_TI"; if (IsConst) Mangler.getStream() << 'C'; if (IsVolatile) Mangler.getStream() << 'V'; + if (IsUnaligned) + Mangler.getStream() << 'U'; Mangler.getStream() << NumEntries; Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); } void MicrosoftMangleContextImpl::mangleCXXCatchableTypeArray( QualType T, uint32_t NumEntries, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "_CTA"; Mangler.getStream() << NumEntries; Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); @@ -2671,17 +2692,20 @@ void MicrosoftMangleContextImpl::mangleCXXCatchableType( llvm::SmallString<64> RTTIMangling; { llvm::raw_svector_ostream Stream(RTTIMangling); - mangleCXXRTTI(T, Stream); + msvc_hashing_ostream MHO(Stream); + mangleCXXRTTI(T, MHO); } Mangler.getStream() << RTTIMangling.substr(1); // VS2015 CTP6 omits the copy-constructor in the mangled name. This name is, // in fact, superfluous but I'm not sure the change was made consciously. - // TODO: Revisit this when VS2015 gets released. llvm::SmallString<64> CopyCtorMangling; - if (CD) { + if (!getASTContext().getLangOpts().isCompatibleWithMSVC( + LangOptions::MSVC2015) && + CD) { llvm::raw_svector_ostream Stream(CopyCtorMangling); - mangleCXXCtor(CD, CT, Stream); + msvc_hashing_ostream MHO(Stream); + mangleCXXCtor(CD, CT, MHO); } Mangler.getStream() << CopyCtorMangling.substr(1); @@ -2700,7 +2724,8 @@ void MicrosoftMangleContextImpl::mangleCXXCatchableType( void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor( const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "\01??_R1"; Mangler.mangleNumber(NVOffset); Mangler.mangleNumber(VBPtrOffset); @@ -2712,7 +2737,8 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor( void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray( const CXXRecordDecl *Derived, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "\01??_R2"; Mangler.mangleName(Derived); Mangler.getStream() << "8"; @@ -2720,7 +2746,8 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray( void MicrosoftMangleContextImpl::mangleCXXRTTIClassHierarchyDescriptor( const CXXRecordDecl *Derived, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "\01??_R3"; Mangler.mangleName(Derived); Mangler.getStream() << "8"; @@ -2733,18 +2760,26 @@ void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator( // <cvr-qualifiers> [<name>] @ // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class> // is always '6' for vftables. - MicrosoftCXXNameMangler Mangler(*this, Out); - Mangler.getStream() << "\01??_R4"; - Mangler.mangleName(Derived); - Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const. - for (const CXXRecordDecl *RD : BasePath) - Mangler.mangleName(RD); - Mangler.getStream() << '@'; + llvm::SmallString<64> VFTableMangling; + llvm::raw_svector_ostream Stream(VFTableMangling); + mangleCXXVFTable(Derived, BasePath, Stream); + + if (VFTableMangling.startswith("\01??@")) { + assert(VFTableMangling.endswith("@")); + Out << VFTableMangling << "??_R4@"; + return; + } + + assert(VFTableMangling.startswith("\01??_7") || + VFTableMangling.startswith("\01??_S")); + + Out << "\01??_R4" << StringRef(VFTableMangling).drop_front(5); } void MicrosoftMangleContextImpl::mangleSEHFilterExpression( const NamedDecl *EnclosingDecl, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); // The function body is in the same comdat as the function with the handler, // so the numbering here doesn't have to be the same across TUs. // @@ -2755,7 +2790,8 @@ void MicrosoftMangleContextImpl::mangleSEHFilterExpression( void MicrosoftMangleContextImpl::mangleSEHFinallyBlock( const NamedDecl *EnclosingDecl, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); // The function body is in the same comdat as the function with the handler, // so the numbering here doesn't have to be the same across TUs. // @@ -2775,20 +2811,23 @@ void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) { void MicrosoftMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, raw_ostream &Out) { - MicrosoftCXXNameMangler mangler(*this, Out, D, Type); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler mangler(*this, MHO, D, Type); mangler.mangle(D); } void MicrosoftMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, raw_ostream &Out) { - MicrosoftCXXNameMangler mangler(*this, Out, D, Type); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler mangler(*this, MHO, D, Type); mangler.mangle(D); } void MicrosoftMangleContextImpl::mangleReferenceTemporary( const VarDecl *VD, unsigned ManglingNumber, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "\01?$RT" << ManglingNumber << '@'; Mangler.mangle(VD, ""); @@ -2796,10 +2835,12 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary( void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable( const VarDecl *VD, unsigned GuardNum, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "\01?$TSS" << GuardNum << '@'; Mangler.mangleNestedName(VD); + Mangler.getStream() << "@4HA"; } void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, @@ -2814,7 +2855,8 @@ void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, // than 32 static locals. We don't fully implement the second mangling // because those guards are not externally visible, and instead use LLVM's // default renaming when creating a new guard variable. - MicrosoftCXXNameMangler Mangler(*this, Out); + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); bool Visible = VD->isExternallyVisible(); if (Visible) { @@ -2836,9 +2878,10 @@ void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, } void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D, - raw_ostream &Out, - char CharCode) { - MicrosoftCXXNameMangler Mangler(*this, Out); + char CharCode, + raw_ostream &Out) { + msvc_hashing_ostream MHO(Out); + MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "\01??__" << CharCode; Mangler.mangleName(D); if (D->isStaticDataMember()) { @@ -2853,14 +2896,14 @@ void MicrosoftMangleContextImpl::mangleInitFiniStub(const VarDecl *D, void MicrosoftMangleContextImpl::mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) { // <initializer-name> ::= ?__E <name> YAXXZ - mangleInitFiniStub(D, Out, 'E'); + mangleInitFiniStub(D, 'E', Out); } void MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D, raw_ostream &Out) { // <destructor-name> ::= ?__F <name> YAXXZ - mangleInitFiniStub(D, Out, 'F'); + mangleInitFiniStub(D, 'F', Out); } void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp index c562dae63231..ac2a8d354247 100644 --- a/lib/AST/NSAPI.cpp +++ b/lib/AST/NSAPI.cpp @@ -441,22 +441,14 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { case BuiltinType::Int128: case BuiltinType::LongDouble: case BuiltinType::UInt128: + case BuiltinType::Float128: case BuiltinType::NullPtr: case BuiltinType::ObjCClass: case BuiltinType::ObjCId: case BuiltinType::ObjCSel: - 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: +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index d2370c88b9c5..82809d7ea7b5 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -171,10 +171,19 @@ NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { /// \brief Retrieve the record declaration stored in this nested name specifier. CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const { - if (Prefix.getInt() == StoredDecl) + switch (Prefix.getInt()) { + case StoredIdentifier: + return nullptr; + + case StoredDecl: return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier)); - return nullptr; + case StoredTypeSpec: + case StoredTypeSpecWithTemplate: + return getAsType()->getAsCXXRecordDecl(); + } + + llvm_unreachable("Invalid NNS Kind!"); } /// \brief Whether this nested name specifier refers to a dependent @@ -306,7 +315,7 @@ NestedNameSpecifier::print(raw_ostream &OS, // Print the template argument list. TemplateSpecializationType::PrintTemplateArgumentList( - OS, SpecType->getArgs(), SpecType->getNumArgs(), InnerPolicy); + OS, SpecType->template_arguments(), InnerPolicy); } else { // Print the type normally QualType(T, 0).print(OS, InnerPolicy); @@ -322,7 +331,7 @@ void NestedNameSpecifier::dump(const LangOptions &LO) const { print(llvm::errs(), PrintingPolicy(LO)); } -void NestedNameSpecifier::dump() const { +LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { LangOptions LO; print(llvm::errs(), PrintingPolicy(LO)); } diff --git a/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp index 1ef43f7694cf..d04ba727bb05 100644 --- a/lib/AST/OpenMPClause.cpp +++ b/lib/AST/OpenMPClause.cpp @@ -29,6 +29,139 @@ OMPClause::child_range OMPClause::children() { llvm_unreachable("unknown OMPClause"); } +OMPClauseWithPreInit *OMPClauseWithPreInit::get(OMPClause *C) { + auto *Res = OMPClauseWithPreInit::get(const_cast<const OMPClause *>(C)); + return Res ? const_cast<OMPClauseWithPreInit *>(Res) : nullptr; +} + +const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { + switch (C->getClauseKind()) { + case OMPC_schedule: + return static_cast<const OMPScheduleClause *>(C); + case OMPC_dist_schedule: + return static_cast<const OMPDistScheduleClause *>(C); + case OMPC_firstprivate: + return static_cast<const OMPFirstprivateClause *>(C); + case OMPC_lastprivate: + return static_cast<const OMPLastprivateClause *>(C); + case OMPC_reduction: + return static_cast<const OMPReductionClause *>(C); + case OMPC_linear: + return static_cast<const OMPLinearClause *>(C); + case OMPC_default: + case OMPC_proc_bind: + case OMPC_if: + case OMPC_final: + case OMPC_num_threads: + case OMPC_safelen: + case OMPC_simdlen: + case OMPC_collapse: + case OMPC_private: + case OMPC_shared: + case OMPC_aligned: + case OMPC_copyin: + case OMPC_copyprivate: + case OMPC_ordered: + case OMPC_nowait: + case OMPC_untied: + case OMPC_mergeable: + case OMPC_threadprivate: + case OMPC_flush: + case OMPC_read: + case OMPC_write: + case OMPC_update: + case OMPC_capture: + case OMPC_seq_cst: + case OMPC_depend: + case OMPC_device: + case OMPC_threads: + case OMPC_simd: + case OMPC_map: + case OMPC_num_teams: + case OMPC_thread_limit: + case OMPC_priority: + case OMPC_grainsize: + case OMPC_nogroup: + case OMPC_num_tasks: + case OMPC_hint: + case OMPC_defaultmap: + case OMPC_unknown: + case OMPC_uniform: + case OMPC_to: + case OMPC_from: + case OMPC_use_device_ptr: + case OMPC_is_device_ptr: + break; + } + + return nullptr; +} + +OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(OMPClause *C) { + auto *Res = OMPClauseWithPostUpdate::get(const_cast<const OMPClause *>(C)); + return Res ? const_cast<OMPClauseWithPostUpdate *>(Res) : nullptr; +} + +const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) { + switch (C->getClauseKind()) { + case OMPC_lastprivate: + return static_cast<const OMPLastprivateClause *>(C); + case OMPC_reduction: + return static_cast<const OMPReductionClause *>(C); + case OMPC_linear: + return static_cast<const OMPLinearClause *>(C); + case OMPC_schedule: + case OMPC_dist_schedule: + case OMPC_firstprivate: + case OMPC_default: + case OMPC_proc_bind: + case OMPC_if: + case OMPC_final: + case OMPC_num_threads: + case OMPC_safelen: + case OMPC_simdlen: + case OMPC_collapse: + case OMPC_private: + case OMPC_shared: + case OMPC_aligned: + case OMPC_copyin: + case OMPC_copyprivate: + case OMPC_ordered: + case OMPC_nowait: + case OMPC_untied: + case OMPC_mergeable: + case OMPC_threadprivate: + case OMPC_flush: + case OMPC_read: + case OMPC_write: + case OMPC_update: + case OMPC_capture: + case OMPC_seq_cst: + case OMPC_depend: + case OMPC_device: + case OMPC_threads: + case OMPC_simd: + case OMPC_map: + case OMPC_num_teams: + case OMPC_thread_limit: + case OMPC_priority: + case OMPC_grainsize: + case OMPC_nogroup: + case OMPC_num_tasks: + case OMPC_hint: + case OMPC_defaultmap: + case OMPC_unknown: + case OMPC_uniform: + case OMPC_to: + case OMPC_from: + case OMPC_use_device_ptr: + case OMPC_is_device_ptr: + break; + } + + return nullptr; +} + void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) { assert(VL.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); @@ -70,13 +203,14 @@ OMPFirstprivateClause * OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL, - ArrayRef<Expr *> InitVL) { + ArrayRef<Expr *> InitVL, Stmt *PreInit) { 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); + Clause->setPreInitStmt(PreInit); return Clause; } @@ -117,7 +251,8 @@ void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { OMPLastprivateClause *OMPLastprivateClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, - ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { + ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps, Stmt *PreInit, + Expr *PostUpdate) { void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size())); OMPLastprivateClause *Clause = new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); @@ -125,6 +260,8 @@ OMPLastprivateClause *OMPLastprivateClause::Create( Clause->setSourceExprs(SrcExprs); Clause->setDestinationExprs(DstExprs); Clause->setAssignmentOps(AssignmentOps); + Clause->setPreInitStmt(PreInit); + Clause->setPostUpdateExpr(PostUpdate); return Clause; } @@ -179,7 +316,8 @@ 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) { + ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep, + Stmt *PreInit, Expr *PostUpdate) { // 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)); @@ -196,6 +334,8 @@ OMPLinearClause *OMPLinearClause::Create( nullptr); Clause->setStep(Step); Clause->setCalcStep(CalcStep); + Clause->setPreInitStmt(PreInit); + Clause->setPostUpdateExpr(PostUpdate); return Clause; } @@ -340,7 +480,8 @@ OMPReductionClause *OMPReductionClause::Create( SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs, - ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps) { + ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit, + Expr *PostUpdate) { void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size())); OMPReductionClause *Clause = new (Mem) OMPReductionClause( StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo); @@ -349,6 +490,8 @@ OMPReductionClause *OMPReductionClause::Create( Clause->setLHSExprs(LHSExprs); Clause->setRHSExprs(RHSExprs); Clause->setReductionOps(ReductionOps); + Clause->setPreInitStmt(PreInit); + Clause->setPostUpdateExpr(PostUpdate); return Clause; } @@ -363,7 +506,7 @@ OMPFlushClause *OMPFlushClause::Create(const ASTContext &C, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1)); OMPFlushClause *Clause = new (Mem) OMPFlushClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); @@ -375,43 +518,252 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned 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 *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() + 1)); OMPDependClause *Clause = new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); Clause->setDependencyKind(DepKind); Clause->setDependencyLoc(DepLoc); Clause->setColonLoc(ColonLoc); + Clause->setCounterValue(nullptr); return Clause; } OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) { - void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + 1)); 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())); +void OMPDependClause::setCounterValue(Expr *V) { + assert(getDependencyKind() == OMPC_DEPEND_sink || + getDependencyKind() == OMPC_DEPEND_source || V == nullptr); + *getVarRefs().end() = V; +} + +const Expr *OMPDependClause::getCounterValue() const { + auto *V = *getVarRefs().end(); + assert(getDependencyKind() == OMPC_DEPEND_sink || + getDependencyKind() == OMPC_DEPEND_source || V == nullptr); + return V; +} + +Expr *OMPDependClause::getCounterValue() { + auto *V = *getVarRefs().end(); + assert(getDependencyKind() == OMPC_DEPEND_sink || + getDependencyKind() == OMPC_DEPEND_source || V == nullptr); + return V; +} + +unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber( + MappableExprComponentListsRef ComponentLists) { + unsigned TotalNum = 0u; + for (auto &C : ComponentLists) + TotalNum += C.size(); + return TotalNum; +} + +unsigned OMPClauseMappableExprCommon::getUniqueDeclarationsTotalNumber( + ArrayRef<ValueDecl *> Declarations) { + unsigned TotalNum = 0u; + llvm::SmallPtrSet<const ValueDecl *, 8> Cache; + for (auto *D : Declarations) { + const ValueDecl *VD = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; + if (Cache.count(VD)) + continue; + ++TotalNum; + Cache.insert(VD); + } + return TotalNum; +} + +OMPMapClause * +OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists, + OpenMPMapClauseKind TypeModifier, OpenMPMapClauseKind Type, + bool TypeIsImplicit, SourceLocation TypeLoc) { + + unsigned NumVars = Vars.size(); + unsigned NumUniqueDeclarations = + getUniqueDeclarationsTotalNumber(Declarations); + unsigned NumComponentLists = ComponentLists.size(); + unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + + // We need to allocate: + // NumVars x Expr* - we have an original list expression for each clause list + // entry. + // NumUniqueDeclarations x ValueDecl* - unique base declarations associated + // with each component list. + // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the + // number of lists for each unique declaration and the size of each component + // list. + // NumComponents x MappableComponent - the total of all the components in all + // the lists. + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); OMPMapClause *Clause = new (Mem) OMPMapClause( - TypeModifier, Type, TypeLoc, StartLoc, LParenLoc, EndLoc, VL.size()); - Clause->setVarRefs(VL); + TypeModifier, Type, TypeIsImplicit, TypeLoc, StartLoc, LParenLoc, EndLoc, + NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents); + + Clause->setVarRefs(Vars); + Clause->setClauseInfo(Declarations, ComponentLists); Clause->setMapTypeModifier(TypeModifier); Clause->setMapType(Type); Clause->setMapLoc(TypeLoc); return Clause; } -OMPMapClause *OMPMapClause::CreateEmpty(const ASTContext &C, unsigned N) { +OMPMapClause *OMPMapClause::CreateEmpty(const ASTContext &C, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, + unsigned NumComponents) { + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + return new (Mem) OMPMapClause(NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); +} + +OMPToClause *OMPToClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> Vars, + ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists) { + unsigned NumVars = Vars.size(); + unsigned NumUniqueDeclarations = + getUniqueDeclarationsTotalNumber(Declarations); + unsigned NumComponentLists = ComponentLists.size(); + unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + + // We need to allocate: + // NumVars x Expr* - we have an original list expression for each clause list + // entry. + // NumUniqueDeclarations x ValueDecl* - unique base declarations associated + // with each component list. + // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the + // number of lists for each unique declaration and the size of each component + // list. + // NumComponents x MappableComponent - the total of all the components in all + // the lists. + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + + OMPToClause *Clause = new (Mem) + OMPToClause(StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); + + Clause->setVarRefs(Vars); + Clause->setClauseInfo(Declarations, ComponentLists); + return Clause; +} + +OMPToClause *OMPToClause::CreateEmpty(const ASTContext &C, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, + unsigned NumComponents) { + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + return new (Mem) OMPToClause(NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); +} + +OMPFromClause * +OMPFromClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists) { + unsigned NumVars = Vars.size(); + unsigned NumUniqueDeclarations = + getUniqueDeclarationsTotalNumber(Declarations); + unsigned NumComponentLists = ComponentLists.size(); + unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + + // We need to allocate: + // NumVars x Expr* - we have an original list expression for each clause list + // entry. + // NumUniqueDeclarations x ValueDecl* - unique base declarations associated + // with each component list. + // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the + // number of lists for each unique declaration and the size of each component + // list. + // NumComponents x MappableComponent - the total of all the components in all + // the lists. + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + + OMPFromClause *Clause = new (Mem) + OMPFromClause(StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); + + Clause->setVarRefs(Vars); + Clause->setClauseInfo(Declarations, ComponentLists); + return Clause; +} + +OMPFromClause *OMPFromClause::CreateEmpty(const ASTContext &C, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, + unsigned NumComponents) { + void *Mem = C.Allocate( + totalSizeToAlloc<Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent>( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + return new (Mem) OMPFromClause(NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); +} + +OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); + OMPUseDevicePtrClause *Clause = + new (Mem) OMPUseDevicePtrClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPUseDevicePtrClause *OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); + return new (Mem) OMPUseDevicePtrClause(N); +} + +OMPIsDevicePtrClause *OMPIsDevicePtrClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); + OMPIsDevicePtrClause *Clause = + new (Mem) OMPIsDevicePtrClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C, + unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); - return new (Mem) OMPMapClause(N); + return new (Mem) OMPIsDevicePtrClause(N); } diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp index d7d5f9c69205..d8882c9030b2 100644 --- a/lib/AST/ParentMap.cpp +++ b/lib/AST/ParentMap.cpp @@ -28,6 +28,8 @@ enum OpaqueValueMode { static void BuildParentMap(MapTy& M, Stmt* S, OpaqueValueMode OVMode = OV_Transparent) { + if (!S) + return; switch (S->getStmtClass()) { case Stmt::PseudoObjectExprClass: { diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp index b2c244e3790e..299fd111bf6a 100644 --- a/lib/AST/RecordLayout.cpp +++ b/lib/AST/RecordLayout.cpp @@ -18,8 +18,6 @@ using namespace clang; void ASTRecordLayout::Destroy(ASTContext &Ctx) { - if (FieldOffsets) - Ctx.Deallocate(FieldOffsets); if (CXXInfo) { CXXInfo->~CXXRecordLayoutInfo(); Ctx.Deallocate(CXXInfo); @@ -29,18 +27,13 @@ void ASTRecordLayout::Destroy(ASTContext &Ctx) { } ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size, - CharUnits alignment, + CharUnits alignment, CharUnits requiredAlignment, CharUnits datasize, - const uint64_t *fieldoffsets, - unsigned fieldcount) - : Size(size), DataSize(datasize), Alignment(alignment), - RequiredAlignment(requiredAlignment), FieldOffsets(nullptr), - FieldCount(fieldcount), CXXInfo(nullptr) { - if (FieldCount > 0) { - FieldOffsets = new (Ctx) uint64_t[FieldCount]; - memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets)); - } + ArrayRef<uint64_t> fieldoffsets) + : Size(size), DataSize(datasize), Alignment(alignment), + RequiredAlignment(requiredAlignment), CXXInfo(nullptr) { + FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end()); } // Constructor for C++ records. @@ -50,26 +43,21 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, bool hasOwnVFPtr, bool hasExtendableVFPtr, CharUnits vbptroffset, CharUnits datasize, - const uint64_t *fieldoffsets, - unsigned fieldcount, + ArrayRef<uint64_t> fieldoffsets, CharUnits nonvirtualsize, CharUnits nonvirtualalignment, CharUnits SizeOfLargestEmptySubobject, const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual, const CXXRecordDecl *BaseSharingVBPtr, - bool HasZeroSizedSubObject, + bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase, const BaseOffsetsMapTy& BaseOffsets, const VBaseOffsetsMapTy& VBaseOffsets) : Size(size), DataSize(datasize), Alignment(alignment), - RequiredAlignment(requiredAlignment), FieldOffsets(nullptr), - FieldCount(fieldcount), CXXInfo(new (Ctx) CXXRecordLayoutInfo) + RequiredAlignment(requiredAlignment), CXXInfo(new (Ctx) CXXRecordLayoutInfo) { - if (FieldCount > 0) { - FieldOffsets = new (Ctx) uint64_t[FieldCount]; - memcpy(FieldOffsets, fieldoffsets, FieldCount * sizeof(*FieldOffsets)); - } + FieldOffsets.append(Ctx, fieldoffsets.begin(), fieldoffsets.end()); CXXInfo->PrimaryBase.setPointer(PrimaryBase); CXXInfo->PrimaryBase.setInt(IsPrimaryBaseVirtual); @@ -82,7 +70,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CXXInfo->VBPtrOffset = vbptroffset; CXXInfo->HasExtendableVFPtr = hasExtendableVFPtr; CXXInfo->BaseSharingVBPtr = BaseSharingVBPtr; - CXXInfo->HasZeroSizedSubObject = HasZeroSizedSubObject; + CXXInfo->EndsWithZeroSizedObject = EndsWithZeroSizedObject; CXXInfo->LeadsWithZeroSizedBase = LeadsWithZeroSizedBase; diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index bc5ae0ffc469..cf981be0a4dd 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -973,7 +973,7 @@ void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment( } // Round up the current record size to pointer alignment. - setSize(getSize().RoundUpToAlignment(BaseAlign)); + setSize(getSize().alignTo(BaseAlign)); setDataSize(getSize()); // Update the alignment. @@ -1194,7 +1194,7 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { if (!HasExternalLayout) { // Round up the current record size to the base's alignment boundary. - Offset = getDataSize().RoundUpToAlignment(BaseAlign); + Offset = getDataSize().alignTo(BaseAlign); // Try to place the base. while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset)) @@ -1204,7 +1204,7 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { (void)Allowed; assert(Allowed && "Base subobject externally placed at overlapping offset"); - if (InferAlignment && Offset < getDataSize().RoundUpToAlignment(BaseAlign)){ + if (InferAlignment && Offset < getDataSize().alignTo(BaseAlign)) { // The externally-supplied base offset is before the base offset we // computed. Assume that the structure is packed. Alignment = CharUnits::One(); @@ -1292,8 +1292,7 @@ void ItaniumRecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { LayoutFields(RD); NonVirtualSize = Context.toCharUnitsFromBits( - llvm::RoundUpToAlignment(getSizeInBits(), - Context.getTargetInfo().getCharAlign())); + llvm::alignTo(getSizeInBits(), Context.getTargetInfo().getCharAlign())); NonVirtualAlignment = Alignment; // Lay out the virtual bases and add the primary virtual base offsets. @@ -1364,7 +1363,7 @@ static uint64_t roundUpSizeToCharAlignment(uint64_t Size, const ASTContext &Context) { uint64_t CharAlignment = Context.getTargetInfo().getCharAlign(); - return llvm::RoundUpToAlignment(Size, CharAlignment); + return llvm::alignTo(Size, CharAlignment); } void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, @@ -1411,13 +1410,12 @@ void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, } else { // The bitfield is allocated starting at the next offset aligned // appropriately for T', with length n bits. - FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(), - Context.toBits(TypeAlign)); + FieldOffset = llvm::alignTo(getDataSizeInBits(), Context.toBits(TypeAlign)); uint64_t NewSizeInBits = FieldOffset + FieldSize; - setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, - Context.getTargetInfo().getCharAlign())); + setDataSize( + llvm::alignTo(NewSizeInBits, Context.getTargetInfo().getCharAlign())); UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits; } @@ -1560,10 +1558,13 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // But, if there's a #pragma pack in play, that takes precedent over // even the 'aligned' attribute, for non-zero-width bitfields. + unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment); if (!MaxFieldAlignment.isZero() && FieldSize) { - unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment); - FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits); + if (FieldPacked) + FieldAlign = UnpackedFieldAlign; + else + FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); } // But, ms_struct just ignores all of that in unions, even explicit @@ -1587,9 +1588,9 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // start a new storage unit), just do so, regardless of any other // other consideration. Otherwise, round up to the right alignment. if (FieldSize == 0 || FieldSize > UnfilledBitsInLastUnit) { - FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); - UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, - UnpackedFieldAlign); + FieldOffset = llvm::alignTo(FieldOffset, FieldAlign); + UnpackedFieldOffset = + llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign); UnfilledBitsInLastUnit = 0; } @@ -1601,22 +1602,28 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { if (FieldSize == 0 || (AllowPadding && (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) { - FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); - } else if (ExplicitFieldAlign) { + FieldOffset = llvm::alignTo(FieldOffset, FieldAlign); + } else if (ExplicitFieldAlign && + (MaxFieldAlignmentInBits == 0 || + ExplicitFieldAlign <= MaxFieldAlignmentInBits) && + Context.getTargetInfo().useExplicitBitFieldAlignment()) { // 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); + FieldOffset = llvm::alignTo(FieldOffset, ExplicitFieldAlign); } // Repeat the computation for diagnostic purposes. if (FieldSize == 0 || (AllowPadding && (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) - UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, - UnpackedFieldAlign); - else if (ExplicitFieldAlign) - UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, - ExplicitFieldAlign); + UnpackedFieldOffset = + llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign); + else if (ExplicitFieldAlign && + (MaxFieldAlignmentInBits == 0 || + ExplicitFieldAlign <= MaxFieldAlignmentInBits) && + Context.getTargetInfo().useExplicitBitFieldAlignment()) + UnpackedFieldOffset = + llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign); } // If we're using external layout, give the external layout a chance @@ -1677,7 +1684,7 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { } else { uint64_t NewSizeInBits = FieldOffset + FieldSize; uint64_t CharAlignment = Context.getTargetInfo().getCharAlign(); - setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, CharAlignment)); + setDataSize(llvm::alignTo(NewSizeInBits, CharAlignment)); UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits; // The only time we can get here for an ms_struct is if this is a @@ -1767,9 +1774,8 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, } // Round up the current record size to the field's alignment boundary. - FieldOffset = FieldOffset.RoundUpToAlignment(FieldAlign); - UnpackedFieldOffset = - UnpackedFieldOffset.RoundUpToAlignment(UnpackedFieldAlign); + FieldOffset = FieldOffset.alignTo(FieldAlign); + UnpackedFieldOffset = UnpackedFieldOffset.alignTo(UnpackedFieldAlign); if (UseExternalLayout) { FieldOffset = Context.toCharUnitsFromBits( @@ -1840,11 +1846,10 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) { // record itself. uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit; uint64_t UnpackedSizeInBits = - llvm::RoundUpToAlignment(getSizeInBits(), - Context.toBits(UnpackedAlignment)); + llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment)); CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits); - uint64_t RoundedSize - = llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment)); + uint64_t RoundedSize = + llvm::alignTo(getSizeInBits(), Context.toBits(Alignment)); if (UseExternalLayout) { // If we're inferring alignment, and the external size is smaller than @@ -2127,7 +2132,7 @@ static bool isMsLayout(const ASTContext &Context) { // function pointer) and a vbptr (virtual base pointer). They can each be // shared with a, non-virtual bases. These bases need not be the same. vfptrs // always occur at offset 0. vbptrs can occur at an arbitrary offset and are -// placed after the lexiographically last non-virtual base. This placement +// placed after the lexicographically last non-virtual base. This placement // is always before fields but can be in the middle of the non-virtual bases // due to the two-pass layout scheme for non-virtual-bases. // * Virtual bases sometimes require a 'vtordisp' field that is laid out before @@ -2148,7 +2153,7 @@ static bool isMsLayout(const ASTContext &Context) { // pushes all bases and fields back by the alignment imposed by those bases // and fields. This can potentially add a significant amount of padding. // vbptrs are injected immediately after the last non-virtual base as -// lexiographically ordered in the code. If this site isn't pointer aligned +// lexicographically ordered in the code. If this site isn't pointer aligned // the vbptr is placed at the next properly aligned location. Enough padding // is added to guarantee a fit. // * The last zero sized non-virtual base can be placed at the end of the @@ -2223,7 +2228,8 @@ public: /// laid out. void initializeCXXLayout(const CXXRecordDecl *RD); void layoutNonVirtualBases(const CXXRecordDecl *RD); - void layoutNonVirtualBase(const CXXRecordDecl *BaseDecl, + void layoutNonVirtualBase(const CXXRecordDecl *RD, + const CXXRecordDecl *BaseDecl, const ASTRecordLayout &BaseLayout, const ASTRecordLayout *&PreviousBaseLayout); void injectVFPtr(const CXXRecordDecl *RD); @@ -2329,7 +2335,7 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( if (!MaxFieldAlignment.isZero()) Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment); // Track zero-sized subobjects here where it's already available. - EndsWithZeroSizedObject = Layout.hasZeroSizedSubObject(); + EndsWithZeroSizedObject = Layout.endsWithZeroSizedObject(); // Respect required alignment, this is necessary because we may have adjusted // the alignment in the case of pragam pack. Note that the required alignment // doesn't actually apply to the struct alignment at this point. @@ -2364,7 +2370,7 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( if (auto RT = FD->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) { auto const &Layout = Context.getASTRecordLayout(RT->getDecl()); - EndsWithZeroSizedObject = Layout.hasZeroSizedSubObject(); + EndsWithZeroSizedObject = Layout.endsWithZeroSizedObject(); FieldRequiredAlignment = std::max(FieldRequiredAlignment, Layout.getRequiredAlignment()); } @@ -2385,7 +2391,7 @@ void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) { MinEmptyStructSize = CharUnits::fromQuantity(4); initializeLayout(RD); layoutFields(RD); - DataSize = Size = Size.RoundUpToAlignment(Alignment); + DataSize = Size = Size.alignTo(Alignment); RequiredAlignment = std::max( RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment())); finalizeLayout(RD); @@ -2405,7 +2411,7 @@ void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) { auto RoundingAlignment = Alignment; if (!MaxFieldAlignment.isZero()) RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment); - NonVirtualSize = Size = Size.RoundUpToAlignment(RoundingAlignment); + NonVirtualSize = Size = Size.alignTo(RoundingAlignment); RequiredAlignment = std::max( RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment())); layoutVirtualBases(RD); @@ -2471,7 +2477,7 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { // out any bases that do not contain vfptrs. We implement this as two passes // over the bases. This approach guarantees that the primary base is laid out // first. We use these passes to calculate some additional aggregated - // information about the bases, such as reqruied alignment and the presence of + // information about the bases, such as required alignment and the presence of // zero sized members. const ASTRecordLayout *PreviousBaseLayout = nullptr; // Iterate through the bases and lay out the non-virtual ones. @@ -2483,7 +2489,7 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { HasVBPtr = true; continue; } - // Check fo a base to share a VBPtr with. + // Check for a base to share a VBPtr with. if (!SharedVBPtrBase && BaseLayout.hasVBPtr()) { SharedVBPtrBase = BaseDecl; HasVBPtr = true; @@ -2497,7 +2503,7 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { LeadsWithZeroSizedBase = BaseLayout.leadsWithZeroSizedBase(); } // Lay out the base. - layoutNonVirtualBase(BaseDecl, BaseLayout, PreviousBaseLayout); + layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout); } // Figure out if we need a fresh VFPtr for this class. if (!PrimaryBase && RD->isDynamicClass()) @@ -2526,7 +2532,7 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { LeadsWithZeroSizedBase = BaseLayout.leadsWithZeroSizedBase(); } // Lay out the base. - layoutNonVirtualBase(BaseDecl, BaseLayout, PreviousBaseLayout); + layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout); VBPtrOffset = Bases[BaseDecl] + BaseLayout.getNonVirtualSize(); } // Set our VBPtroffset if we know it at this point. @@ -2538,15 +2544,32 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { } } +static bool recordUsesEBO(const RecordDecl *RD) { + if (!isa<CXXRecordDecl>(RD)) + return false; + if (RD->hasAttr<EmptyBasesAttr>()) + return true; + if (auto *LVA = RD->getAttr<LayoutVersionAttr>()) + // TODO: Double check with the next version of MSVC. + if (LVA->getVersion() <= LangOptions::MSVC2015) + return false; + // TODO: Some later version of MSVC will change the default behavior of the + // compiler to enable EBO by default. When this happens, we will need an + // additional isCompatibleWithMSVC check. + return false; +} + void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase( + const CXXRecordDecl *RD, const CXXRecordDecl *BaseDecl, const ASTRecordLayout &BaseLayout, const ASTRecordLayout *&PreviousBaseLayout) { // Insert padding between two bases if the left first one is zero sized or // contains a zero sized subobject and the right is zero sized or one leads // with a zero sized base. - if (PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() && - BaseLayout.leadsWithZeroSizedBase()) + bool MDCUsesEBO = recordUsesEBO(RD); + if (PreviousBaseLayout && PreviousBaseLayout->endsWithZeroSizedObject() && + BaseLayout.leadsWithZeroSizedBase() && !MDCUsesEBO) Size++; ElementInfo Info = getAdjustedElementInfo(BaseLayout); CharUnits BaseOffset; @@ -2555,14 +2578,23 @@ void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase( bool FoundBase = false; if (UseExternalLayout) { FoundBase = External.getExternalNVBaseOffset(BaseDecl, BaseOffset); - if (FoundBase) + if (FoundBase) { assert(BaseOffset >= Size && "base offset already allocated"); + Size = BaseOffset; + } } - if (!FoundBase) - BaseOffset = Size.RoundUpToAlignment(Info.Alignment); + if (!FoundBase) { + if (MDCUsesEBO && BaseDecl->isEmpty() && + BaseLayout.getNonVirtualSize() == CharUnits::Zero()) { + BaseOffset = CharUnits::Zero(); + } else { + // Otherwise, lay the base out at the end of the MDC. + BaseOffset = Size = Size.alignTo(Info.Alignment); + } + } Bases.insert(std::make_pair(BaseDecl, BaseOffset)); - Size = BaseOffset + BaseLayout.getNonVirtualSize(); + Size += BaseLayout.getNonVirtualSize(); PreviousBaseLayout = &BaseLayout; } @@ -2590,7 +2622,7 @@ void MicrosoftRecordLayoutBuilder::layoutField(const FieldDecl *FD) { Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD)); assert(FieldOffset >= Size && "field offset already allocated"); } else { - FieldOffset = Size.RoundUpToAlignment(Info.Alignment); + FieldOffset = Size.alignTo(Info.Alignment); } placeFieldAtOffset(FieldOffset); Size = FieldOffset + Info.Size; @@ -2625,7 +2657,7 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. } else { // Allocate a new block of memory and place the bitfield in it. - CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment); + CharUnits FieldOffset = Size.alignTo(Info.Alignment); placeFieldAtOffset(FieldOffset); Size = FieldOffset + Info.Size; Alignment = std::max(Alignment, Info.Alignment); @@ -2651,7 +2683,7 @@ MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) { // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. } else { // Round up the current record size to the field's alignment boundary. - CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment); + CharUnits FieldOffset = Size.alignTo(Info.Alignment); placeFieldAtOffset(FieldOffset); Size = FieldOffset; Alignment = std::max(Alignment, Info.Alignment); @@ -2664,7 +2696,7 @@ void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) { // Inject the VBPointer at the injection site. CharUnits InjectionSite = VBPtrOffset; // But before we do, make sure it's properly aligned. - VBPtrOffset = VBPtrOffset.RoundUpToAlignment(PointerInfo.Alignment); + VBPtrOffset = VBPtrOffset.alignTo(PointerInfo.Alignment); // Shift everything after the vbptr down, unless we're using an external // layout. if (UseExternalLayout) @@ -2673,8 +2705,8 @@ void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) { CharUnits FieldStart = VBPtrOffset + PointerInfo.Size; // Make sure that the amount we push the fields back by is a multiple of the // alignment. - CharUnits Offset = (FieldStart - InjectionSite).RoundUpToAlignment( - std::max(RequiredAlignment, Alignment)); + CharUnits Offset = (FieldStart - InjectionSite) + .alignTo(std::max(RequiredAlignment, Alignment)); Size += Offset; for (uint64_t &FieldOffset : FieldOffsets) FieldOffset += Context.toBits(Offset); @@ -2688,8 +2720,8 @@ void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) { return; // Make sure that the amount we push the struct back by is a multiple of the // alignment. - CharUnits Offset = PointerInfo.Size.RoundUpToAlignment( - std::max(RequiredAlignment, Alignment)); + CharUnits Offset = + PointerInfo.Size.alignTo(std::max(RequiredAlignment, Alignment)); // 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) @@ -2741,9 +2773,10 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { // with a zero sized base. The padding between virtual bases is 4 // bytes (in both 32 and 64 bits modes) and always involves rounding up to // the required alignment, we don't know why. - if ((PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() && - BaseLayout.leadsWithZeroSizedBase()) || HasVtordisp) { - Size = Size.RoundUpToAlignment(VtorDispAlignment) + VtorDispSize; + if ((PreviousBaseLayout && PreviousBaseLayout->endsWithZeroSizedObject() && + BaseLayout.leadsWithZeroSizedBase() && !recordUsesEBO(RD)) || + HasVtordisp) { + Size = Size.alignTo(VtorDispAlignment) + VtorDispSize; Alignment = std::max(VtorDispAlignment, Alignment); } // Insert the virtual base. @@ -2758,7 +2791,7 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) { assert(BaseOffset >= Size && "base offset already allocated"); } if (!FoundBase) - BaseOffset = Size.RoundUpToAlignment(Info.Alignment); + BaseOffset = Size.alignTo(Info.Alignment); VBases.insert(std::make_pair(BaseDecl, ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp))); @@ -2777,11 +2810,13 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) { if (!MaxFieldAlignment.isZero()) RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment); RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment); - Size = Size.RoundUpToAlignment(RoundingAlignment); + Size = Size.alignTo(RoundingAlignment); } if (Size.isZero()) { - EndsWithZeroSizedObject = true; - LeadsWithZeroSizedBase = true; + if (!recordUsesEBO(RD) || !cast<CXXRecordDecl>(RD)->isEmpty()) { + EndsWithZeroSizedObject = true; + LeadsWithZeroSizedBase = true; + } // Zero-sized structures have size equal to their alignment if a // __declspec(align) came into play. if (RequiredAlignment >= MinEmptyStructSize) @@ -2914,8 +2949,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { 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.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets, Builder.NonVirtualSize, Builder.Alignment, CharUnits::Zero(), Builder.PrimaryBase, false, Builder.SharedVBPtrBase, Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase, @@ -2924,8 +2958,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { Builder.layout(D); NewEntry = new (*this) ASTRecordLayout( *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment, - Builder.Size, Builder.FieldOffsets.data(), - Builder.FieldOffsets.size()); + Builder.Size, Builder.FieldOffsets); } } else { if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { @@ -2948,9 +2981,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { *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, + CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets, + NonVirtualSize, Builder.NonVirtualAlignment, EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase, Builder.PrimaryBaseIsVirtual, nullptr, false, false, Builder.Bases, Builder.VBases); @@ -2961,8 +2993,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { NewEntry = new (*this) ASTRecordLayout( *this, Builder.getSize(), Builder.Alignment, /*RequiredAlignment : used by MS-ABI)*/ - Builder.Alignment, Builder.getSize(), Builder.FieldOffsets.data(), - Builder.FieldOffsets.size()); + Builder.Alignment, Builder.getSize(), Builder.FieldOffsets); } } @@ -3065,7 +3096,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, // Add in synthesized ivar count if laying out an implementation. if (Impl) { unsigned SynthCount = CountNonClassIvars(D); - // If there aren't any sythesized ivars then reuse the interface + // If there aren't any synthesized ivars then reuse the interface // entry. Note we can't cache this because we simply free all // entries later; however we shouldn't look up implementations // frequently. @@ -3077,13 +3108,12 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, Builder.Layout(D); const ASTRecordLayout *NewEntry = - new (*this) ASTRecordLayout(*this, Builder.getSize(), + new (*this) ASTRecordLayout(*this, Builder.getSize(), Builder.Alignment, /*RequiredAlignment : used by MS-ABI)*/ Builder.Alignment, Builder.getDataSize(), - Builder.FieldOffsets.data(), - Builder.FieldOffsets.size()); + Builder.FieldOffsets); ObjCLayouts[Key] = NewEntry; diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index ca63d8486d82..75c076399511 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -503,6 +503,9 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, bool HasVariants = !C.getTargetInfo().hasNoAsmVariants(); + unsigned LastAsmStringToken = 0; + unsigned LastAsmStringOffset = 0; + while (1) { // Done with the string? if (CurPtr == StrEnd) { @@ -589,10 +592,12 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, // (BeginLoc, EndLoc) represents the range of the operand we are currently // processing. Unlike Str, the range includes the leading '%'. - SourceLocation BeginLoc = - getAsmString()->getLocationOfByte(Percent - StrStart, SM, LO, TI); - SourceLocation EndLoc = - getAsmString()->getLocationOfByte(CurPtr - StrStart, SM, LO, TI); + SourceLocation BeginLoc = getAsmString()->getLocationOfByte( + Percent - StrStart, SM, LO, TI, &LastAsmStringToken, + &LastAsmStringOffset); + SourceLocation EndLoc = getAsmString()->getLocationOfByte( + CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken, + &LastAsmStringOffset); Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); continue; @@ -623,10 +628,12 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, // (BeginLoc, EndLoc) represents the range of the operand we are currently // processing. Unlike Str, the range includes the leading '%'. - SourceLocation BeginLoc = - getAsmString()->getLocationOfByte(Percent - StrStart, SM, LO, TI); - SourceLocation EndLoc = - getAsmString()->getLocationOfByte(NameEnd + 1 - StrStart, SM, LO, TI); + SourceLocation BeginLoc = getAsmString()->getLocationOfByte( + Percent - StrStart, SM, LO, TI, &LastAsmStringToken, + &LastAsmStringOffset); + SourceLocation EndLoc = getAsmString()->getLocationOfByte( + NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken, + &LastAsmStringOffset); Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); @@ -756,11 +763,13 @@ void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr, }); } -IfStmt::IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, - Stmt *then, SourceLocation EL, Stmt *elsev) - : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) -{ +IfStmt::IfStmt(const ASTContext &C, SourceLocation IL, bool IsConstexpr, + Stmt *init, VarDecl *var, Expr *cond, Stmt *then, + SourceLocation EL, Stmt *elsev) + : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) { + setConstexpr(IsConstexpr); setConditionVariable(C, var); + SubExprs[INIT] = init; SubExprs[COND] = cond; SubExprs[THEN] = then; SubExprs[ELSE] = elsev; @@ -816,9 +825,11 @@ void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { VarRange.getEnd()); } -SwitchStmt::SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond) +SwitchStmt::SwitchStmt(const ASTContext &C, Stmt *init, VarDecl *Var, + Expr *cond) : Stmt(SwitchStmtClass), FirstCase(nullptr, false) { setConditionVariable(C, Var); + SubExprs[INIT] = init; SubExprs[COND] = cond; SubExprs[BODY] = nullptr; } @@ -987,8 +998,7 @@ CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const { unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); // Offset of the first Capture object. - unsigned FirstCaptureOffset = - llvm::RoundUpToAlignment(Size, llvm::alignOf<Capture>()); + unsigned FirstCaptureOffset = llvm::alignTo(Size, llvm::alignOf<Capture>()); return reinterpret_cast<Capture *>( reinterpret_cast<char *>(const_cast<CapturedStmt *>(this)) @@ -1045,7 +1055,7 @@ CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S, unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1); if (!Captures.empty()) { // Realign for the following Capture array. - Size = llvm::RoundUpToAlignment(Size, llvm::alignOf<Capture>()); + Size = llvm::alignTo(Size, llvm::alignOf<Capture>()); Size += sizeof(Capture) * Captures.size(); } @@ -1058,7 +1068,7 @@ CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context, unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); if (NumCaptures > 0) { // Realign for the following Capture array. - Size = llvm::RoundUpToAlignment(Size, llvm::alignOf<Capture>()); + Size = llvm::alignTo(Size, llvm::alignOf<Capture>()); Size += sizeof(Capture) * NumCaptures; } diff --git a/lib/AST/StmtCXX.cpp b/lib/AST/StmtCXX.cpp index e39a01daf96c..4692db84b505 100644 --- a/lib/AST/StmtCXX.cpp +++ b/lib/AST/StmtCXX.cpp @@ -49,7 +49,8 @@ CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, std::copy(handlers.begin(), handlers.end(), Stmts + 1); } -CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt, +CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, + DeclStmt *BeginStmt, DeclStmt *EndStmt, Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body, SourceLocation FL, SourceLocation CAL, SourceLocation CL, @@ -57,7 +58,8 @@ CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt, : Stmt(CXXForRangeStmtClass), ForLoc(FL), CoawaitLoc(CAL), ColonLoc(CL), RParenLoc(RPL) { SubExprs[RANGE] = Range; - SubExprs[BEGINEND] = BeginEndStmt; + SubExprs[BEGINSTMT] = BeginStmt; + SubExprs[ENDSTMT] = EndStmt; SubExprs[COND] = Cond; SubExprs[INC] = Inc; SubExprs[LOOPVAR] = LoopVar; diff --git a/lib/AST/StmtOpenMP.cpp b/lib/AST/StmtOpenMP.cpp index 7f923d8a8251..f1ddedb2b0f2 100644 --- a/lib/AST/StmtOpenMP.cpp +++ b/lib/AST/StmtOpenMP.cpp @@ -57,8 +57,8 @@ void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) { 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 *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPParallelDirective *Dir = @@ -72,8 +72,8 @@ OMPParallelDirective *OMPParallelDirective::Create( OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPParallelDirective(NumClauses); @@ -84,8 +84,8 @@ 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 *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd)); @@ -105,6 +105,7 @@ OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } @@ -112,8 +113,8 @@ OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd)); @@ -125,8 +126,8 @@ 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 *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); @@ -148,11 +149,15 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, Dir->setEnsureUpperBound(Exprs.EUB); Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); Dir->setHasCancel(HasCancel); return Dir; } @@ -161,8 +166,8 @@ OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); @@ -174,8 +179,8 @@ 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 *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPForSimdDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); @@ -197,11 +202,15 @@ OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, Dir->setEnsureUpperBound(Exprs.EUB); Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } @@ -209,8 +218,8 @@ OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPForSimdDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd)); @@ -220,8 +229,8 @@ OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C, 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 *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPSectionsDirective *Dir = @@ -235,8 +244,8 @@ OMPSectionsDirective *OMPSectionsDirective::Create( OMPSectionsDirective *OMPSectionsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPSectionsDirective(NumClauses); @@ -247,8 +256,8 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective), - llvm::alignOf<Stmt *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc); Dir->setAssociatedStmt(AssociatedStmt); @@ -258,8 +267,8 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C, OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective), - llvm::alignOf<Stmt *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size + sizeof(Stmt *)); return new (Mem) OMPSectionDirective(); } @@ -269,8 +278,8 @@ OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSingleDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPSingleDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPSingleDirective *Dir = @@ -283,8 +292,8 @@ OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C, OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSingleDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPSingleDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPSingleDirective(NumClauses); @@ -294,8 +303,8 @@ OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPMasterDirective), - llvm::alignOf<Stmt *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPMasterDirective), llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPMasterDirective *Dir = new (Mem) OMPMasterDirective(StartLoc, EndLoc); Dir->setAssociatedStmt(AssociatedStmt); @@ -304,8 +313,8 @@ OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C, OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPMasterDirective), - llvm::alignOf<Stmt *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPMasterDirective), llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size + sizeof(Stmt *)); return new (Mem) OMPMasterDirective(); } @@ -314,8 +323,8 @@ 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 *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPCriticalDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPCriticalDirective *Dir = @@ -328,8 +337,8 @@ OMPCriticalDirective *OMPCriticalDirective::Create( OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPCriticalDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPCriticalDirective(NumClauses); @@ -339,8 +348,8 @@ 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 *>()); + unsigned Size = llvm::alignTo(sizeof(OMPParallelForDirective), + llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for)); @@ -362,11 +371,15 @@ OMPParallelForDirective *OMPParallelForDirective::Create( Dir->setEnsureUpperBound(Exprs.EUB); Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); Dir->setHasCancel(HasCancel); return Dir; } @@ -374,8 +387,8 @@ OMPParallelForDirective *OMPParallelForDirective::Create( OMPParallelForDirective * OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPParallelForDirective), + llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for)); @@ -386,8 +399,8 @@ 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 *>()); + unsigned Size = llvm::alignTo(sizeof(OMPParallelForSimdDirective), + llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); @@ -409,11 +422,15 @@ OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create( Dir->setEnsureUpperBound(Exprs.EUB); Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } @@ -421,8 +438,8 @@ OMPParallelForSimdDirective * OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPParallelForSimdDirective), + llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate( Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd)); @@ -432,8 +449,8 @@ OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C, 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 *>()); + unsigned Size = llvm::alignTo(sizeof(OMPParallelSectionsDirective), + llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPParallelSectionsDirective *Dir = @@ -447,8 +464,8 @@ OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( OMPParallelSectionsDirective * OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelSectionsDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPParallelSectionsDirective), + llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPParallelSectionsDirective(NumClauses); @@ -458,8 +475,8 @@ 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 *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTaskDirective *Dir = @@ -473,8 +490,8 @@ OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc, OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTaskDirective(NumClauses); @@ -527,8 +544,8 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective), - llvm::alignOf<Stmt *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTaskgroupDirective), llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size + sizeof(Stmt *)); OMPTaskgroupDirective *Dir = new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc); @@ -538,8 +555,8 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C, OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective), - llvm::alignOf<Stmt *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTaskgroupDirective), llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size + sizeof(Stmt *)); return new (Mem) OMPTaskgroupDirective(); } @@ -547,8 +564,8 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C, OMPCancellationPointDirective *OMPCancellationPointDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) { - unsigned Size = llvm::RoundUpToAlignment( - sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPCancellationPointDirective), + llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size); OMPCancellationPointDirective *Dir = new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc); @@ -558,8 +575,8 @@ OMPCancellationPointDirective *OMPCancellationPointDirective::Create( OMPCancellationPointDirective * OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment( - sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPCancellationPointDirective), + llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size); return new (Mem) OMPCancellationPointDirective(); } @@ -568,9 +585,9 @@ 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 *>()); + unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) + + sizeof(OMPClause *) * Clauses.size(), + llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size); OMPCancelDirective *Dir = new (Mem) OMPCancelDirective(StartLoc, EndLoc, Clauses.size()); @@ -582,9 +599,9 @@ OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc, OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective) + - sizeof(OMPClause *) * NumClauses, - llvm::alignOf<Stmt *>()); + unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) + + sizeof(OMPClause *) * NumClauses, + llvm::alignOf<Stmt *>()); void *Mem = C.Allocate(Size); return new (Mem) OMPCancelDirective(NumClauses); } @@ -593,8 +610,8 @@ OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPFlushDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPFlushDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size()); OMPFlushDirective *Dir = new (Mem) OMPFlushDirective(StartLoc, EndLoc, Clauses.size()); @@ -605,8 +622,8 @@ OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C, OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPFlushDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPFlushDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses); return new (Mem) OMPFlushDirective(NumClauses); } @@ -616,8 +633,8 @@ OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPOrderedDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * Clauses.size()); OMPOrderedDirective *Dir = @@ -630,8 +647,8 @@ OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C, OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPOrderedDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * NumClauses); return new (Mem) OMPOrderedDirective(NumClauses); @@ -641,8 +658,8 @@ 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 *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + 5 * sizeof(Stmt *)); OMPAtomicDirective *Dir = @@ -661,8 +678,8 @@ OMPAtomicDirective *OMPAtomicDirective::Create( OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *)); return new (Mem) OMPAtomicDirective(NumClauses); @@ -673,8 +690,8 @@ OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTargetDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetDirective *Dir = @@ -687,20 +704,95 @@ OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C, OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTargetDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTargetDirective(NumClauses); } -OMPTargetDataDirective *OMPTargetDataDirective::Create( +OMPTargetParallelDirective *OMPTargetParallelDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelDirective), + llvm::alignOf<OMPClause *>()); void *Mem = - C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPTargetDataDirective), - llvm::alignOf<OMPClause *>()) + - sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTargetParallelDirective *Dir = + new (Mem) OMPTargetParallelDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTargetParallelDirective * +OMPTargetParallelDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell) { + unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTargetParallelDirective(NumClauses); +} + +OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs, bool HasCancel) { + unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for)); + OMPTargetParallelForDirective *Dir = new (Mem) OMPTargetParallelForDirective( + 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->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + Dir->setHasCancel(HasCancel); + return Dir; +} + +OMPTargetParallelForDirective * +OMPTargetParallelForDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for)); + return new (Mem) OMPTargetParallelForDirective(CollapsedNum, NumClauses); +} + +OMPTargetDataDirective *OMPTargetDataDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) { + void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetDataDirective), + llvm::alignOf<OMPClause *>()) + + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTargetDataDirective *Dir = new (Mem) OMPTargetDataDirective(StartLoc, EndLoc, Clauses.size()); Dir->setClauses(Clauses); @@ -711,20 +803,62 @@ OMPTargetDataDirective *OMPTargetDataDirective::Create( 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 *)); + void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetDataDirective), + llvm::alignOf<OMPClause *>()) + + sizeof(OMPClause *) * N + sizeof(Stmt *)); return new (Mem) OMPTargetDataDirective(N); } +OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses) { + void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetEnterDataDirective), + llvm::alignOf<OMPClause *>()) + + sizeof(OMPClause *) * Clauses.size()); + OMPTargetEnterDataDirective *Dir = + new (Mem) OMPTargetEnterDataDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + return Dir; +} + +OMPTargetEnterDataDirective * +OMPTargetEnterDataDirective::CreateEmpty(const ASTContext &C, unsigned N, + EmptyShell) { + void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetEnterDataDirective), + llvm::alignOf<OMPClause *>()) + + sizeof(OMPClause *) * N); + return new (Mem) OMPTargetEnterDataDirective(N); +} + +OMPTargetExitDataDirective * +OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses) { + void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetExitDataDirective), + llvm::alignOf<OMPClause *>()) + + sizeof(OMPClause *) * Clauses.size()); + OMPTargetExitDataDirective *Dir = + new (Mem) OMPTargetExitDataDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + return Dir; +} + +OMPTargetExitDataDirective * +OMPTargetExitDataDirective::CreateEmpty(const ASTContext &C, unsigned N, + EmptyShell) { + void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetExitDataDirective), + llvm::alignOf<OMPClause *>()) + + sizeof(OMPClause *) * N); + return new (Mem) OMPTargetExitDataDirective(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 *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTeamsDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); OMPTeamsDirective *Dir = @@ -737,8 +871,8 @@ OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C, OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTeamsDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); return new (Mem) OMPTeamsDirective(NumClauses); @@ -748,8 +882,8 @@ 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 *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTaskLoopDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop)); @@ -771,11 +905,15 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::Create( Dir->setEnsureUpperBound(Exprs.EUB); Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } @@ -783,8 +921,8 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskLoopDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = + llvm::alignTo(sizeof(OMPTaskLoopDirective), llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop)); @@ -795,8 +933,8 @@ 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 *>()); + unsigned Size = llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), + llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop_simd)); @@ -818,19 +956,23 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create( Dir->setEnsureUpperBound(Exprs.EUB); Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } OMPTaskLoopSimdDirective * OMPTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskLoopSimdDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), + llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop_simd)); @@ -841,8 +983,8 @@ 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 *>()); + unsigned Size = llvm::alignTo(sizeof(OMPDistributeDirective), + llvm::alignOf<OMPClause *>()); void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_distribute)); @@ -864,21 +1006,267 @@ OMPDistributeDirective *OMPDistributeDirective::Create( Dir->setEnsureUpperBound(Exprs.EUB); Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); + Dir->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } OMPDistributeDirective * OMPDistributeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell) { - unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPDistributeDirective), - llvm::alignOf<OMPClause *>()); + unsigned Size = llvm::alignTo(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); } + +OMPTargetUpdateDirective * +OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses) { + unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size()); + OMPTargetUpdateDirective *Dir = + new (Mem) OMPTargetUpdateDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + return Dir; +} + +OMPTargetUpdateDirective * +OMPTargetUpdateDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses); + return new (Mem) OMPTargetUpdateDirective(NumClauses); +} + +OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for)); + OMPDistributeParallelForDirective *Dir = + new (Mem) OMPDistributeParallelForDirective(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->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPDistributeParallelForDirective * +OMPDistributeParallelForDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for)); + return new (Mem) OMPDistributeParallelForDirective(CollapsedNum, NumClauses); +} + +OMPDistributeParallelForSimdDirective * +OMPDistributeParallelForSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for_simd)); + OMPDistributeParallelForSimdDirective *Dir = new (Mem) + OMPDistributeParallelForSimdDirective(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->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPDistributeParallelForSimdDirective * +OMPDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_distribute_parallel_for_simd)); + return new (Mem) + OMPDistributeParallelForSimdDirective(CollapsedNum, NumClauses); +} + +OMPDistributeSimdDirective *OMPDistributeSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::alignTo(sizeof(OMPDistributeSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_distribute_simd)); + OMPDistributeSimdDirective *Dir = new (Mem) OMPDistributeSimdDirective( + 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->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPDistributeSimdDirective * +OMPDistributeSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = llvm::alignTo(sizeof(OMPDistributeSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_distribute_simd)); + return new (Mem) OMPDistributeSimdDirective(CollapsedNum, NumClauses); +} + +OMPTargetParallelForSimdDirective *OMPTargetParallelForSimdDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + const HelperExprs &Exprs) { + unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * Clauses.size() + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd)); + OMPTargetParallelForSimdDirective *Dir = + new (Mem) OMPTargetParallelForSimdDirective(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->setNumIterations(Exprs.NumIterations); + Dir->setPrevLowerBoundVariable(Exprs.PrevLB); + Dir->setPrevUpperBoundVariable(Exprs.PrevUB); + Dir->setCounters(Exprs.Counters); + Dir->setPrivateCounters(Exprs.PrivateCounters); + Dir->setInits(Exprs.Inits); + Dir->setUpdates(Exprs.Updates); + Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); + return Dir; +} + +OMPTargetParallelForSimdDirective * +OMPTargetParallelForSimdDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell) { + unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = C.Allocate( + Size + sizeof(OMPClause *) * NumClauses + + sizeof(Stmt *) * + numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd)); + return new (Mem) OMPTargetParallelForSimdDirective(CollapsedNum, NumClauses); +} diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 69f52f52b669..8797a13335c4 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -16,6 +16,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -496,6 +497,11 @@ void StmtPrinter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *Node) { OS << ";\n"; } +void StmtPrinter::VisitObjCAvailabilityCheckExpr( + ObjCAvailabilityCheckExpr *Node) { + OS << "@available(...)"; +} + void StmtPrinter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Node) { Indent() << "@synchronized ("; PrintExpr(Node->getSynchExpr()); @@ -663,9 +669,9 @@ void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) { OS << ": "; } OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind()); - if (Node->getChunkSize()) { + if (auto *E = Node->getChunkSize()) { OS << ", "; - Node->getChunkSize()->printPretty(OS, nullptr, Policy); + E->printPretty(OS, nullptr, Policy); } OS << ")"; } @@ -763,15 +769,16 @@ template<typename T> void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) { for (typename T::varlist_iterator I = Node->varlist_begin(), E = Node->varlist_end(); - I != E; ++I) { + I != E; ++I) { assert(*I && "Expected non-null Stmt"); + OS << (I == Node->varlist_begin() ? StartSym : ','); if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*I)) { - OS << (I == Node->varlist_begin() ? StartSym : ','); - cast<NamedDecl>(DRE->getDecl())->printQualifiedName(OS); - } else { - OS << (I == Node->varlist_begin() ? StartSym : ','); + if (isa<OMPCapturedExprDecl>(DRE->getDecl())) + DRE->printPretty(OS, nullptr, Policy, 0); + else + DRE->getDecl()->printQualifiedName(OS); + } else (*I)->printPretty(OS, nullptr, Policy, 0); - } } } @@ -909,6 +916,58 @@ void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) { OS << ")"; } } + +void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) { + if (!Node->varlist_empty()) { + OS << "to"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPFromClause(OMPFromClause *Node) { + if (!Node->varlist_empty()) { + OS << "from"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) { + OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName( + OMPC_dist_schedule, Node->getDistScheduleKind()); + if (auto *E = Node->getChunkSize()) { + OS << ", "; + E->printPretty(OS, nullptr, Policy); + } + OS << ")"; +} + +void OMPClausePrinter::VisitOMPDefaultmapClause(OMPDefaultmapClause *Node) { + OS << "defaultmap("; + OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap, + Node->getDefaultmapModifier()); + OS << ": "; + OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap, + Node->getDefaultmapKind()); + OS << ")"; +} + +void OMPClausePrinter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *Node) { + if (!Node->varlist_empty()) { + OS << "use_device_ptr"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + +void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) { + if (!Node->varlist_empty()) { + OS << "is_device_ptr"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} } //===----------------------------------------------------------------------===// @@ -1051,6 +1110,30 @@ void StmtPrinter::VisitOMPTargetDataDirective(OMPTargetDataDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTargetEnterDataDirective( + OMPTargetEnterDataDirective *Node) { + Indent() << "#pragma omp target enter data "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetExitDataDirective( + OMPTargetExitDataDirective *Node) { + Indent() << "#pragma omp target exit data "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetParallelDirective( + OMPTargetParallelDirective *Node) { + Indent() << "#pragma omp target parallel "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetParallelForDirective( + OMPTargetParallelForDirective *Node) { + Indent() << "#pragma omp target parallel for "; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) { Indent() << "#pragma omp teams "; PrintOMPExecutableDirective(Node); @@ -1085,11 +1168,45 @@ void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTargetUpdateDirective( + OMPTargetUpdateDirective *Node) { + Indent() << "#pragma omp target update "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPDistributeParallelForDirective( + OMPDistributeParallelForDirective *Node) { + Indent() << "#pragma omp distribute parallel for "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPDistributeParallelForSimdDirective( + OMPDistributeParallelForSimdDirective *Node) { + Indent() << "#pragma omp distribute parallel for simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPDistributeSimdDirective( + OMPDistributeSimdDirective *Node) { + Indent() << "#pragma omp distribute simd "; + PrintOMPExecutableDirective(Node); +} + +void StmtPrinter::VisitOMPTargetParallelForSimdDirective( + OMPTargetParallelForSimdDirective *Node) { + Indent() << "#pragma omp target parallel for simd "; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { + if (auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) { + OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy); + return; + } if (NestedNameSpecifier *Qualifier = Node->getQualifier()) Qualifier->print(OS, Policy); if (Node->hasTemplateKeyword()) @@ -1097,7 +1214,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); + OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitDependentScopeDeclRefExpr( @@ -1109,7 +1226,7 @@ void StmtPrinter::VisitDependentScopeDeclRefExpr( OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); + OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { @@ -1120,7 +1237,7 @@ void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); + OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { @@ -1204,6 +1321,12 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { OS << "'\\v'"; break; default: + // A character literal might be sign-extended, which + // would result in an invalid \U escape sequence. + // FIXME: multicharacter literals such as '\xFF\xFF\xFF\xFF' + // are not correctly handled. + if ((value & ~0xFFu) == ~0xFFu && Node->getKind() == CharacterLiteral::Ascii) + value &= 0xFFu; if (value < 256 && isPrintable((unsigned char)value)) OS << "'" << (char)value << "'"; else if (value < 256) @@ -1254,6 +1377,7 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node, case BuiltinType::Double: break; // no suffix. case BuiltinType::Float: OS << 'F'; break; case BuiltinType::LongDouble: OS << 'L'; break; + case BuiltinType::Float128: OS << 'Q'; break; } } @@ -1340,9 +1464,9 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){ OS << "sizeof"; break; case UETT_AlignOf: - if (Policy.LangOpts.CPlusPlus) + if (Policy.Alignof) OS << "alignof"; - else if (Policy.LangOpts.C11) + else if (Policy.UnderscoreAlignof) OS << "_Alignof"; else OS << "__alignof"; @@ -1440,7 +1564,7 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) { OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); + OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) { PrintExpr(Node->getBase()); @@ -1563,26 +1687,24 @@ void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) { void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) { bool NeedsEquals = true; - for (DesignatedInitExpr::designators_iterator D = Node->designators_begin(), - DEnd = Node->designators_end(); - D != DEnd; ++D) { - if (D->isFieldDesignator()) { - if (D->getDotLoc().isInvalid()) { - if (IdentifierInfo *II = D->getFieldName()) { + for (const DesignatedInitExpr::Designator &D : Node->designators()) { + if (D.isFieldDesignator()) { + if (D.getDotLoc().isInvalid()) { + if (IdentifierInfo *II = D.getFieldName()) { OS << II->getName() << ":"; NeedsEquals = false; } } else { - OS << "." << D->getFieldName()->getName(); + OS << "." << D.getFieldName()->getName(); } } else { OS << "["; - if (D->isArrayDesignator()) { - PrintExpr(Node->getArrayIndex(*D)); + if (D.isArrayDesignator()) { + PrintExpr(Node->getArrayIndex(D)); } else { - PrintExpr(Node->getArrayRangeStart(*D)); + PrintExpr(Node->getArrayRangeStart(D)); OS << " ... "; - PrintExpr(Node->getArrayRangeEnd(*D)); + PrintExpr(Node->getArrayRangeEnd(D)); } OS << "]"; } @@ -1612,7 +1734,7 @@ void StmtPrinter::VisitNoInitExpr(NoInitExpr *Node) { } void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) { - if (Policy.LangOpts.CPlusPlus) { + if (Node->getType()->getAsCXXRecordDecl()) { OS << "/*implicit*/"; Node->getType().print(OS, Policy); OS << "()"; @@ -1822,7 +1944,7 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { if (Args->size() != 1) { OS << "operator\"\"" << Node->getUDSuffix()->getName(); TemplateSpecializationType::PrintTemplateArgumentList( - OS, Args->data(), Args->size(), Policy); + OS, Args->asArray(), Policy); OS << "()"; return; } @@ -1952,7 +2074,9 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { case LCK_This: OS << "this"; break; - + case LCK_StarThis: + OS << "*this"; + break; case LCK_ByRef: if (Node->getCaptureDefault() != LCD_ByRef || Node->isInitCapture(C)) OS << '&'; @@ -1975,7 +2099,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { OS << " ("; CXXMethodDecl *Method = Node->getCallOperator(); NeedComma = false; - for (auto P : Method->params()) { + for (auto P : Method->parameters()) { if (NeedComma) { OS << ", "; } else { @@ -2103,6 +2227,11 @@ void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { OS << "}"; } +void StmtPrinter::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E) { + // Parens are printed by the surrounding context. + OS << "<forwarded>"; +} + void StmtPrinter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { PrintExpr(E->getSubExpr()); } @@ -2140,7 +2269,7 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr( OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); + OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { @@ -2155,7 +2284,7 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); + OS, Node->template_arguments(), Policy); } static const char *getTypeTraitName(TypeTrait TT) { @@ -2424,7 +2553,7 @@ void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { void StmtPrinter::VisitTypoExpr(TypoExpr *Node) { // TODO: Print something reasonable for a TypoExpr, if necessary. - assert(false && "Cannot print TypoExpr nodes"); + llvm_unreachable("Cannot print TypoExpr nodes"); } void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 175a43abbf61..0a39413853a0 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -69,6 +69,7 @@ namespace { } void StmtProfiler::VisitStmt(const Stmt *S) { + assert(S && "Requires non-null Stmt pointer"); ID.AddInteger(S->getStmtClass()); for (const Stmt *SubStmt : S->children()) { if (SubStmt) @@ -268,8 +269,23 @@ public: #define OPENMP_CLAUSE(Name, Class) \ void Visit##Class(const Class *C); #include "clang/Basic/OpenMPKinds.def" + void VistOMPClauseWithPreInit(const OMPClauseWithPreInit *C); + void VistOMPClauseWithPostUpdate(const OMPClauseWithPostUpdate *C); }; +void OMPClauseProfiler::VistOMPClauseWithPreInit( + const OMPClauseWithPreInit *C) { + if (auto *S = C->getPreInitStmt()) + Profiler->VisitStmt(S); +} + +void OMPClauseProfiler::VistOMPClauseWithPostUpdate( + const OMPClauseWithPostUpdate *C) { + VistOMPClauseWithPreInit(C); + if (auto *E = C->getPostUpdateExpr()) + Profiler->VisitStmt(E); +} + void OMPClauseProfiler::VisitOMPIfClause(const OMPIfClause *C) { if (C->getCondition()) Profiler->VisitStmt(C->getCondition()); @@ -305,12 +321,9 @@ void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { } void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { } void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) { - if (C->getChunkSize()) { - Profiler->VisitStmt(C->getChunkSize()); - if (C->getHelperChunkSize()) { - Profiler->VisitStmt(C->getChunkSize()); - } - } + VistOMPClauseWithPreInit(C); + if (auto *S = C->getChunkSize()) + Profiler->VisitStmt(S); } void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *C) { @@ -343,37 +356,46 @@ void OMPClauseProfiler::VisitOMPNogroupClause(const OMPNogroupClause *) {} template<typename T> void OMPClauseProfiler::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } } void OMPClauseProfiler::VisitOMPPrivateClause(const OMPPrivateClause *C) { VisitOMPClauseList(C); for (auto *E : C->private_copies()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } } void OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) { VisitOMPClauseList(C); + VistOMPClauseWithPreInit(C); for (auto *E : C->private_copies()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->inits()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } } void OMPClauseProfiler::VisitOMPLastprivateClause(const OMPLastprivateClause *C) { VisitOMPClauseList(C); + VistOMPClauseWithPostUpdate(C); for (auto *E : C->source_exprs()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->destination_exprs()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->assignment_ops()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } } void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) { @@ -385,63 +407,82 @@ void OMPClauseProfiler::VisitOMPReductionClause( C->getQualifierLoc().getNestedNameSpecifier()); Profiler->VisitName(C->getNameInfo().getName()); VisitOMPClauseList(C); + VistOMPClauseWithPostUpdate(C); for (auto *E : C->privates()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->lhs_exprs()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->rhs_exprs()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->reduction_ops()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } } void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) { VisitOMPClauseList(C); + VistOMPClauseWithPostUpdate(C); for (auto *E : C->privates()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->inits()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->updates()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->finals()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } - Profiler->VisitStmt(C->getStep()); - Profiler->VisitStmt(C->getCalcStep()); + if (C->getStep()) + Profiler->VisitStmt(C->getStep()); + if (C->getCalcStep()) + Profiler->VisitStmt(C->getCalcStep()); } void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) { VisitOMPClauseList(C); - Profiler->VisitStmt(C->getAlignment()); + if (C->getAlignment()) + Profiler->VisitStmt(C->getAlignment()); } void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) { VisitOMPClauseList(C); for (auto *E : C->source_exprs()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->destination_exprs()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->assignment_ops()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } } void OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) { VisitOMPClauseList(C); for (auto *E : C->source_exprs()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->destination_exprs()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } for (auto *E : C->assignment_ops()) { - Profiler->VisitStmt(E); + if (E) + Profiler->VisitStmt(E); } } void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) { @@ -451,29 +492,50 @@ void OMPClauseProfiler::VisitOMPDependClause(const OMPDependClause *C) { VisitOMPClauseList(C); } void OMPClauseProfiler::VisitOMPDeviceClause(const OMPDeviceClause *C) { - Profiler->VisitStmt(C->getDevice()); + if (C->getDevice()) + Profiler->VisitStmt(C->getDevice()); } void OMPClauseProfiler::VisitOMPMapClause(const OMPMapClause *C) { VisitOMPClauseList(C); } void OMPClauseProfiler::VisitOMPNumTeamsClause(const OMPNumTeamsClause *C) { - Profiler->VisitStmt(C->getNumTeams()); + if (C->getNumTeams()) + Profiler->VisitStmt(C->getNumTeams()); } void OMPClauseProfiler::VisitOMPThreadLimitClause( const OMPThreadLimitClause *C) { - Profiler->VisitStmt(C->getThreadLimit()); + if (C->getThreadLimit()) + Profiler->VisitStmt(C->getThreadLimit()); } void OMPClauseProfiler::VisitOMPPriorityClause(const OMPPriorityClause *C) { - Profiler->VisitStmt(C->getPriority()); + if (C->getPriority()) + Profiler->VisitStmt(C->getPriority()); } void OMPClauseProfiler::VisitOMPGrainsizeClause(const OMPGrainsizeClause *C) { - Profiler->VisitStmt(C->getGrainsize()); + if (C->getGrainsize()) + Profiler->VisitStmt(C->getGrainsize()); } void OMPClauseProfiler::VisitOMPNumTasksClause(const OMPNumTasksClause *C) { - Profiler->VisitStmt(C->getNumTasks()); + if (C->getNumTasks()) + Profiler->VisitStmt(C->getNumTasks()); } void OMPClauseProfiler::VisitOMPHintClause(const OMPHintClause *C) { - Profiler->VisitStmt(C->getHint()); + if (C->getHint()) + Profiler->VisitStmt(C->getHint()); +} +void OMPClauseProfiler::VisitOMPToClause(const OMPToClause *C) { + VisitOMPClauseList(C); +} +void OMPClauseProfiler::VisitOMPFromClause(const OMPFromClause *C) { + VisitOMPClauseList(C); +} +void OMPClauseProfiler::VisitOMPUseDevicePtrClause( + const OMPUseDevicePtrClause *C) { + VisitOMPClauseList(C); +} +void OMPClauseProfiler::VisitOMPIsDevicePtrClause( + const OMPIsDevicePtrClause *C) { + VisitOMPClauseList(C); } } @@ -584,6 +646,26 @@ void StmtProfiler::VisitOMPTargetDataDirective(const OMPTargetDataDirective *S) VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPTargetEnterDataDirective( + const OMPTargetEnterDataDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPTargetExitDataDirective( + const OMPTargetExitDataDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPTargetParallelDirective( + const OMPTargetParallelDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPTargetParallelForDirective( + const OMPTargetParallelForDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitOMPTeamsDirective(const OMPTeamsDirective *S) { VisitOMPExecutableDirective(S); } @@ -611,6 +693,40 @@ void StmtProfiler::VisitOMPDistributeDirective( VisitOMPLoopDirective(S); } +void OMPClauseProfiler::VisitOMPDistScheduleClause( + const OMPDistScheduleClause *C) { + VistOMPClauseWithPreInit(C); + if (auto *S = C->getChunkSize()) + Profiler->VisitStmt(S); +} + +void OMPClauseProfiler::VisitOMPDefaultmapClause(const OMPDefaultmapClause *) {} + +void StmtProfiler::VisitOMPTargetUpdateDirective( + const OMPTargetUpdateDirective *S) { + VisitOMPExecutableDirective(S); +} + +void StmtProfiler::VisitOMPDistributeParallelForDirective( + const OMPDistributeParallelForDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPDistributeParallelForSimdDirective( + const OMPDistributeParallelForSimdDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPDistributeSimdDirective( + const OMPDistributeSimdDirective *S) { + VisitOMPLoopDirective(S); +} + +void StmtProfiler::VisitOMPTargetParallelForSimdDirective( + const OMPTargetParallelForSimdDirective *S) { + VisitOMPLoopDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } @@ -810,22 +926,20 @@ void StmtProfiler::VisitInitListExpr(const InitListExpr *S) { void StmtProfiler::VisitDesignatedInitExpr(const DesignatedInitExpr *S) { VisitExpr(S); ID.AddBoolean(S->usesGNUSyntax()); - for (DesignatedInitExpr::const_designators_iterator D = - S->designators_begin(), DEnd = S->designators_end(); - D != DEnd; ++D) { - if (D->isFieldDesignator()) { + for (const DesignatedInitExpr::Designator &D : S->designators()) { + if (D.isFieldDesignator()) { ID.AddInteger(0); - VisitName(D->getFieldName()); + VisitName(D.getFieldName()); continue; } - if (D->isArrayDesignator()) { + if (D.isArrayDesignator()) { ID.AddInteger(1); } else { - assert(D->isArrayRangeDesignator()); + assert(D.isArrayRangeDesignator()); ID.AddInteger(2); } - ID.AddInteger(D->getFirstExprIndex()); + ID.AddInteger(D.getFirstExprIndex()); } } @@ -1196,6 +1310,12 @@ void StmtProfiler::VisitCXXConstructExpr(const CXXConstructExpr *S) { ID.AddBoolean(S->isElidable()); } +void StmtProfiler::VisitCXXInheritedCtorInitExpr( + const CXXInheritedCtorInitExpr *S) { + VisitExpr(S); + VisitDecl(S->getConstructor()); +} + void StmtProfiler::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) { VisitExplicitCastExpr(S); } @@ -1213,6 +1333,7 @@ StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) { C != CEnd; ++C) { ID.AddInteger(C->getCaptureKind()); switch (C->getCaptureKind()) { + case LCK_StarThis: case LCK_This: break; case LCK_ByRef: @@ -1511,6 +1632,11 @@ void StmtProfiler::VisitObjCBridgedCastExpr(const ObjCBridgedCastExpr *S) { ID.AddBoolean(S->getBridgeKind()); } +void StmtProfiler::VisitObjCAvailabilityCheckExpr( + const ObjCAvailabilityCheckExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitDecl(const Decl *D) { ID.AddInteger(D? D->getKind() : 0); diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index e9edb0df66df..b75ede862f7a 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -415,6 +415,15 @@ void TemplateArgument::print(const PrintingPolicy &Policy, } } +void TemplateArgument::dump(raw_ostream &Out) const { + LangOptions LO; // FIXME! see also TemplateName::dump(). + LO.CPlusPlus = true; + LO.Bool = true; + print(PrintingPolicy(LO), Out); +} + +LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); } + //===----------------------------------------------------------------------===// // TemplateArgumentLoc Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp index 47e0255d52ef..47a7d47e7a48 100644 --- a/lib/AST/TemplateName.cpp +++ b/lib/AST/TemplateName.cpp @@ -227,6 +227,6 @@ void TemplateName::dump(raw_ostream &OS) const { print(OS, PrintingPolicy(LO)); } -void TemplateName::dump() const { +LLVM_DUMP_METHOD void TemplateName::dump() const { dump(llvm::errs()); } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index b467dac66b57..99b024701aa3 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -64,7 +64,7 @@ const IdentifierInfo* QualType::getBaseTypeIdentifier() const { return nullptr; } -bool QualType::isConstant(QualType T, ASTContext &Ctx) { +bool QualType::isConstant(QualType T, const ASTContext &Ctx) { if (T.isConstQualified()) return true; @@ -74,7 +74,7 @@ bool QualType::isConstant(QualType T, ASTContext &Ctx) { return T.getAddressSpace() == LangAS::opencl_constant; } -unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context, +unsigned ConstantArrayType::getNumAddressingBits(const ASTContext &Context, QualType ElementType, const llvm::APInt &NumElements) { uint64_t ElementSize = Context.getTypeSizeInChars(ElementType).getQuantity(); @@ -109,7 +109,7 @@ unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context, return TotalSize.getActiveBits(); } -unsigned ConstantArrayType::getMaxSizeBits(ASTContext &Context) { +unsigned ConstantArrayType::getMaxSizeBits(const ASTContext &Context) { unsigned Bits = Context.getTypeSize(Context.getSizeType()); // Limit the number of bits in size_t so that maximal bit size fits 64 bit @@ -1274,6 +1274,12 @@ QualType QualType::stripObjCKindOfType(const ASTContext &constCtx) const { }); } +QualType QualType::getAtomicUnqualifiedType() const { + if (auto AT = getTypePtr()->getAs<AtomicType>()) + return AT->getValueType().getUnqualifiedType(); + return getUnqualifiedType(); +} + Optional<ArrayRef<QualType>> Type::getObjCSubstitutions( const DeclContext *dc) const { // Look through method scopes. @@ -1616,7 +1622,7 @@ bool Type::hasIntegerRepresentation() const { /// \param Ctx The context in which this type occurs. /// /// \returns true if the type is considered an integral type, false otherwise. -bool Type::isIntegralType(ASTContext &Ctx) const { +bool Type::isIntegralType(const ASTContext &Ctx) const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Int128; @@ -1777,7 +1783,7 @@ bool Type::hasUnsignedIntegerRepresentation() const { bool Type::isFloatingType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Half && - BT->getKind() <= BuiltinType::LongDouble; + BT->getKind() <= BuiltinType::Float128; if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType)) return CT->getElementType()->isFloatingType(); return false; @@ -1799,7 +1805,7 @@ bool Type::isRealFloatingType() const { bool Type::isRealType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::LongDouble; + BT->getKind() <= BuiltinType::Float128; if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); return false; @@ -1808,7 +1814,7 @@ bool Type::isRealType() const { bool Type::isArithmeticType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::LongDouble; + BT->getKind() <= BuiltinType::Float128; if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2). // If a body isn't seen by the time we get here, return false. @@ -1958,7 +1964,7 @@ bool Type::isIncompleteType(NamedDecl **Def) const { } } -bool QualType::isPODType(ASTContext &Context) const { +bool QualType::isPODType(const ASTContext &Context) const { // C++11 has a more relaxed definition of POD. if (Context.getLangOpts().CPlusPlus11) return isCXX11PODType(Context); @@ -1966,7 +1972,7 @@ bool QualType::isPODType(ASTContext &Context) const { return isCXX98PODType(Context); } -bool QualType::isCXX98PODType(ASTContext &Context) const { +bool QualType::isCXX98PODType(const ASTContext &Context) const { // The compiler shouldn't query this for incomplete types, but the user might. // We return false for that case. Except for incomplete arrays of PODs, which // are PODs according to the standard. @@ -2026,7 +2032,7 @@ bool QualType::isCXX98PODType(ASTContext &Context) const { } } -bool QualType::isTrivialType(ASTContext &Context) const { +bool QualType::isTrivialType(const ASTContext &Context) const { // The compiler shouldn't query this for incomplete types, but the user might. // We return false for that case. Except for incomplete arrays of PODs, which // are PODs according to the standard. @@ -2089,7 +2095,7 @@ bool QualType::isTrivialType(ASTContext &Context) const { return false; } -bool QualType::isTriviallyCopyableType(ASTContext &Context) const { +bool QualType::isTriviallyCopyableType(const ASTContext &Context) const { if ((*this)->isArrayType()) return Context.getBaseElementType(*this).isTriviallyCopyableType(Context); @@ -2249,7 +2255,7 @@ bool Type::isStandardLayoutType() const { // This is effectively the intersection of isTrivialType and // isStandardLayoutType. We implement it directly to avoid redundant // conversions from a type to a CXXRecordDecl. -bool QualType::isCXX11PODType(ASTContext &Context) const { +bool QualType::isCXX11PODType(const ASTContext &Context) const { const Type *ty = getTypePtr(); if (ty->isDependentType()) return false; @@ -2454,19 +2460,20 @@ StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { DependentTemplateSpecializationType::DependentTemplateSpecializationType( ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, - unsigned NumArgs, const TemplateArgument *Args, + ArrayRef<TemplateArgument> Args, QualType Canon) : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, true, /*VariablyModified=*/false, NNS && NNS->containsUnexpandedParameterPack()), - NNS(NNS), Name(Name), NumArgs(NumArgs) { + NNS(NNS), Name(Name), NumArgs(Args.size()) { assert((!NNS || NNS->isDependent()) && "DependentTemplateSpecializatonType requires dependent qualifier"); - for (unsigned I = 0; I != NumArgs; ++I) { - if (Args[I].containsUnexpandedParameterPack()) + TemplateArgument *ArgBuffer = getArgBuffer(); + for (const TemplateArgument &Arg : Args) { + if (Arg.containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); - new (&getArgBuffer()[I]) TemplateArgument(Args[I]); + new (ArgBuffer++) TemplateArgument(Arg); } } @@ -2476,13 +2483,12 @@ DependentTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, NestedNameSpecifier *Qualifier, const IdentifierInfo *Name, - unsigned NumArgs, - const TemplateArgument *Args) { + ArrayRef<TemplateArgument> Args) { ID.AddInteger(Keyword); ID.AddPointer(Qualifier); ID.AddPointer(Name); - for (unsigned Idx = 0; Idx < NumArgs; ++Idx) - Args[Idx].Profile(ID, Context); + for (const TemplateArgument &Arg : Args) + Arg.Profile(ID, Context); } bool Type::isElaboratedTypeSpecifier() const { @@ -2552,6 +2558,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { return "double"; case LongDouble: return "long double"; + case Float128: + return "__float128"; case WChar_S: case WChar_U: return Policy.MSWChar ? "__wchar_t" : "wchar_t"; @@ -2581,30 +2589,10 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { 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"; +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case Id: \ + return "__" #Access " " #ImgType "_t"; +#include "clang/Basic/OpenCLImageTypes.def" case OCLSampler: return "sampler_t"; case OCLEvent: @@ -2654,7 +2642,10 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_AAPCS_VFP: return "aapcs-vfp"; case CC_IntelOclBicc: return "intel_ocl_bicc"; case CC_SpirFunction: return "spir_function"; - case CC_SpirKernel: return "spir_kernel"; + case CC_OpenCLKernel: return "opencl_kernel"; + case CC_Swift: return "swiftcall"; + case CC_PreserveMost: return "preserve_most"; + case CC_PreserveAll: return "preserve_all"; } llvm_unreachable("Invalid calling convention."); @@ -2671,7 +2662,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, NumParams(params.size()), NumExceptions(epi.ExceptionSpec.Exceptions.size()), ExceptionSpecType(epi.ExceptionSpec.Type), - HasAnyConsumedParams(epi.ConsumedParameters != nullptr), + HasExtParameterInfos(epi.ExtParameterInfos != nullptr), Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn) { assert(NumParams == params.size() && "function has too many parameters"); @@ -2737,10 +2728,11 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params, slot[0] = epi.ExceptionSpec.SourceDecl; } - if (epi.ConsumedParameters) { - bool *consumedParams = const_cast<bool *>(getConsumedParamsBuffer()); + if (epi.ExtParameterInfos) { + ExtParameterInfo *extParamInfos = + const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer()); for (unsigned i = 0; i != NumParams; ++i) - consumedParams[i] = epi.ConsumedParameters[i]; + extParamInfos[i] = epi.ExtParameterInfos[i]; } } @@ -2860,9 +2852,9 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, epi.ExceptionSpec.Type == EST_Unevaluated) { ID.AddPointer(epi.ExceptionSpec.SourceDecl->getCanonicalDecl()); } - if (epi.ConsumedParameters) { + if (epi.ExtParameterInfos) { for (unsigned i = 0; i != NumParams; ++i) - ID.AddBoolean(epi.ConsumedParameters[i]); + ID.AddInteger(epi.ExtParameterInfos[i].getOpaqueValue()); } epi.ExtInfo.Profile(ID); ID.AddBoolean(epi.HasTrailingReturn); @@ -2931,6 +2923,24 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID, E->Profile(ID, Context, true); } +UnaryTransformType::UnaryTransformType(QualType BaseType, + QualType UnderlyingType, + UTTKind UKind, + QualType CanonicalType) + : Type(UnaryTransform, CanonicalType, BaseType->isDependentType(), + BaseType->isInstantiationDependentType(), + BaseType->isVariablyModifiedType(), + BaseType->containsUnexpandedParameterPack()) + , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) +{} + +DependentUnaryTransformType::DependentUnaryTransformType(const ASTContext &C, + QualType BaseType, + UTTKind UKind) + : UnaryTransformType(BaseType, C.DependentTy, UKind, QualType()) +{} + + TagType::TagType(TypeClass TC, const TagDecl *D, QualType can) : Type(TC, can, D->isDependentType(), /*InstantiationDependent=*/D->isDependentType(), @@ -2947,17 +2957,6 @@ static TagDecl *getInterestingTagDecl(TagDecl *decl) { return decl; } -UnaryTransformType::UnaryTransformType(QualType BaseType, - QualType UnderlyingType, - UTTKind UKind, - QualType CanonicalType) - : Type(UnaryTransform, CanonicalType, UnderlyingType->isDependentType(), - UnderlyingType->isInstantiationDependentType(), - UnderlyingType->isVariablyModifiedType(), - BaseType->containsUnexpandedParameterPack()) - , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind) -{} - TagDecl *TagType::getDecl() const { return getInterestingTagDecl(decl); } @@ -2994,8 +2993,11 @@ bool AttributedType::isQualifier() const { case AttributedType::attr_stdcall: case AttributedType::attr_thiscall: case AttributedType::attr_pascal: + case AttributedType::attr_swiftcall: case AttributedType::attr_vectorcall: case AttributedType::attr_inteloclbicc: + case AttributedType::attr_preserve_most: + case AttributedType::attr_preserve_all: case AttributedType::attr_ms_abi: case AttributedType::attr_sysv_abi: case AttributedType::attr_ptr32: @@ -3047,11 +3049,14 @@ bool AttributedType::isCallingConv() const { case attr_fastcall: case attr_stdcall: case attr_thiscall: + case attr_swiftcall: case attr_vectorcall: case attr_pascal: case attr_ms_abi: case attr_sysv_abi: case attr_inteloclbicc: + case attr_preserve_most: + case attr_preserve_all: return true; } llvm_unreachable("invalid attr kind"); @@ -3095,20 +3100,20 @@ void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID, bool TemplateSpecializationType:: anyDependentTemplateArguments(const TemplateArgumentListInfo &Args, bool &InstantiationDependent) { - return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size(), + return anyDependentTemplateArguments(Args.arguments(), InstantiationDependent); } bool TemplateSpecializationType:: -anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N, +anyDependentTemplateArguments(ArrayRef<TemplateArgumentLoc> Args, bool &InstantiationDependent) { - for (unsigned i = 0; i != N; ++i) { - if (Args[i].getArgument().isDependent()) { + for (const TemplateArgumentLoc &ArgLoc : Args) { + if (ArgLoc.getArgument().isDependent()) { InstantiationDependent = true; return true; } - - if (Args[i].getArgument().isInstantiationDependent()) + + if (ArgLoc.getArgument().isInstantiationDependent()) InstantiationDependent = true; } return false; @@ -3116,7 +3121,7 @@ anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N, TemplateSpecializationType:: TemplateSpecializationType(TemplateName T, - const TemplateArgument *Args, unsigned NumArgs, + ArrayRef<TemplateArgument> Args, QualType Canon, QualType AliasedType) : Type(TemplateSpecialization, Canon.isNull()? QualType(this, 0) : Canon, @@ -3124,7 +3129,7 @@ TemplateSpecializationType(TemplateName T, Canon.isNull()? true : Canon->isInstantiationDependentType(), false, T.containsUnexpandedParameterPack()), - Template(T), NumArgs(NumArgs), TypeAlias(!AliasedType.isNull()) { + Template(T), NumArgs(Args.size()), TypeAlias(!AliasedType.isNull()) { assert(!T.getAsDependentTemplateName() && "Use DependentTemplateSpecializationType for dependent template-name"); assert((T.getKind() == TemplateName::Template || @@ -3134,7 +3139,7 @@ TemplateSpecializationType(TemplateName T, TemplateArgument *TemplateArgs = reinterpret_cast<TemplateArgument *>(this + 1); - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { + for (const TemplateArgument &Arg : Args) { // Update instantiation-dependent and variably-modified bits. // If the canonical type exists and is non-dependent, the template // specialization type can be non-dependent even if one of the type @@ -3143,14 +3148,14 @@ TemplateSpecializationType(TemplateName T, // U<T> is always non-dependent, irrespective of the type T. // However, U<Ts> contains an unexpanded parameter pack, even though // its expansion (and thus its desugared type) doesn't. - if (Args[Arg].isInstantiationDependent()) + if (Arg.isInstantiationDependent()) setInstantiationDependent(); - if (Args[Arg].getKind() == TemplateArgument::Type && - Args[Arg].getAsType()->isVariablyModifiedType()) + if (Arg.getKind() == TemplateArgument::Type && + Arg.getAsType()->isVariablyModifiedType()) setVariablyModified(); - if (Args[Arg].containsUnexpandedParameterPack()) + if (Arg.containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); - new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]); + new (TemplateArgs++) TemplateArgument(Arg); } // Store the aliased type if this is a type alias template specialization. @@ -3163,12 +3168,11 @@ TemplateSpecializationType(TemplateName T, void TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, TemplateName T, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef<TemplateArgument> Args, const ASTContext &Context) { T.Profile(ID); - for (unsigned Idx = 0; Idx < NumArgs; ++Idx) - Args[Idx].Profile(ID, Context); + for (const TemplateArgument &Arg : Args) + Arg.Profile(ID, Context); } QualType @@ -3561,18 +3565,9 @@ bool Type::canHaveNullability() const { case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: - 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: +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index d08b07b2ccd6..78947d18f953 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -80,11 +80,11 @@ unsigned TypeLoc::getFullDataSizeForType(QualType Ty) { while (!TyLoc.isNull()) { unsigned Align = getLocalAlignmentForType(TyLoc.getType()); MaxAlign = std::max(Align, MaxAlign); - Total = llvm::RoundUpToAlignment(Total, Align); + Total = llvm::alignTo(Total, Align); Total += TypeSizer().Visit(TyLoc); TyLoc = TyLoc.getNextTypeLoc(); } - Total = llvm::RoundUpToAlignment(Total, MaxAlign); + Total = llvm::alignTo(Total, MaxAlign); return Total; } @@ -149,12 +149,12 @@ void TypeLoc::copy(TypeLoc other) { // If both data pointers are aligned to the maximum alignment, we // can memcpy because getFullDataSize() accurately reflects the // layout of the data. - if (reinterpret_cast<uintptr_t>(Data) - == llvm::RoundUpToAlignment(reinterpret_cast<uintptr_t>(Data), - TypeLocMaxDataAlign) && - reinterpret_cast<uintptr_t>(other.Data) - == llvm::RoundUpToAlignment(reinterpret_cast<uintptr_t>(other.Data), - TypeLocMaxDataAlign)) { + if (reinterpret_cast<uintptr_t>(Data) == + llvm::alignTo(reinterpret_cast<uintptr_t>(Data), + TypeLocMaxDataAlign) && + reinterpret_cast<uintptr_t>(other.Data) == + llvm::alignTo(reinterpret_cast<uintptr_t>(other.Data), + TypeLocMaxDataAlign)) { memcpy(Data, other.Data, getFullDataSize()); return; } @@ -320,6 +320,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: + case BuiltinType::Float128: llvm_unreachable("Builtin type needs extra local data!"); // Fall through, if the impossible happens. @@ -333,18 +334,9 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: - 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: +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index b202523bdaf3..065a2db09141 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -81,12 +81,14 @@ namespace { class TypePrinter { PrintingPolicy Policy; + unsigned Indentation; bool HasEmptyPlaceHolder; bool InsideCCAttribute; public: - explicit TypePrinter(const PrintingPolicy &Policy) - : Policy(Policy), HasEmptyPlaceHolder(false), InsideCCAttribute(false) { } + explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0) + : Policy(Policy), Indentation(Indentation), + HasEmptyPlaceHolder(false), InsideCCAttribute(false) { } void print(const Type *ty, Qualifiers qs, raw_ostream &OS, StringRef PlaceHolder); @@ -110,7 +112,8 @@ namespace { }; } -static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, bool C99) { +static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, + bool HasRestrictKeyword) { bool appendSpace = false; if (TypeQuals & Qualifiers::Const) { OS << "const"; @@ -123,7 +126,7 @@ static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, bool C99) { } if (TypeQuals & Qualifiers::Restrict) { if (appendSpace) OS << ' '; - if (C99) { + if (HasRestrictKeyword) { OS << "restrict"; } else { OS << "__restrict"; @@ -411,7 +414,7 @@ void TypePrinter::printMemberPointerBefore(const MemberPointerType *T, OS << '('; PrintingPolicy InnerPolicy(Policy); - InnerPolicy.SuppressTag = false; + InnerPolicy.IncludeTagDefinition = false; TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef()); OS << "::*"; @@ -437,7 +440,8 @@ void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T, raw_ostream &OS) { OS << '['; if (T->getIndexTypeQualifiers().hasQualifiers()) { - AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99); + AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), + Policy.Restrict); OS << ' '; } @@ -470,7 +474,7 @@ void TypePrinter::printVariableArrayAfter(const VariableArrayType *T, raw_ostream &OS) { OS << '['; if (T->getIndexTypeQualifiers().hasQualifiers()) { - AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99); + AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.Restrict); OS << ' '; } @@ -629,6 +633,20 @@ void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T, } } +llvm::StringRef clang::getParameterABISpelling(ParameterABI ABI) { + switch (ABI) { + case ParameterABI::Ordinary: + llvm_unreachable("asking for spelling of ordinary parameter ABI"); + case ParameterABI::SwiftContext: + return "swift_context"; + case ParameterABI::SwiftErrorResult: + return "swift_error_result"; + case ParameterABI::SwiftIndirectResult: + return "swift_indirect_result"; + } + llvm_unreachable("bad parameter ABI kind"); +} + void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, raw_ostream &OS) { // If needed for precedence reasons, wrap the inner part in grouping parens. @@ -641,6 +659,13 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, ParamPolicyRAII ParamPolicy(Policy); for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) { if (i) OS << ", "; + + auto EPI = T->getExtParameterInfo(i); + if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) "; + auto ABI = EPI.getABI(); + if (ABI != ParameterABI::Ordinary) + OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) "; + print(T->getParamType(i), OS, StringRef()); } } @@ -649,7 +674,7 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, if (T->getNumParams()) OS << ", "; OS << "..."; - } else if (T->getNumParams() == 0 && !Policy.LangOpts.CPlusPlus) { + } else if (T->getNumParams() == 0 && Policy.UseVoidForZeroParams) { // Do not emit int() if we have a proto, emit 'int(void)'. OS << "void"; } @@ -700,9 +725,18 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, OS << " __attribute__((sysv_abi))"; break; case CC_SpirFunction: - case CC_SpirKernel: + case CC_OpenCLKernel: // Do nothing. These CCs are not available as attributes. break; + case CC_Swift: + OS << " __attribute__((swiftcall))"; + break; + case CC_PreserveMost: + OS << " __attribute__((preserve_most))"; + break; + case CC_PreserveAll: + OS << " __attribute__((preserve_all))"; + break; } } @@ -714,7 +748,7 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, if (unsigned quals = T->getTypeQuals()) { OS << ' '; - AppendTypeQualList(OS, quals, Policy.LangOpts.C99); + AppendTypeQualList(OS, quals, Policy.Restrict); } switch (T->getRefQualifier()) { @@ -863,7 +897,8 @@ void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { } void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - OS << "pipe"; + OS << "pipe "; + print(T->getElementType(), OS, StringRef()); spaceBeforePlaceHolder(OS); } @@ -888,10 +923,8 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); OS << Spec->getIdentifier()->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList(OS, - TemplateArgs.data(), - TemplateArgs.size(), - Policy); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, TemplateArgs.asArray(), Policy); OS << "::"; } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl()) @@ -904,18 +937,19 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) { } void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { - if (Policy.SuppressTag) + if (Policy.IncludeTagDefinition) { + PrintingPolicy SubPolicy = Policy; + SubPolicy.IncludeTagDefinition = false; + D->print(OS, SubPolicy, Indentation); + spaceBeforePlaceHolder(OS); return; + } bool HasKindDecoration = false; - // bool SuppressTagKeyword - // = Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword; - // We don't print tags unless this is an elaborated type. // In C, we just assume every RecordType is an elaborated type. - if (!(Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword || - D->getTypedefNameForAnonDecl())) { + if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) { HasKindDecoration = true; OS << D->getKindName(); OS << ' '; @@ -967,22 +1001,17 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { // arguments. if (ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(D)) { - const TemplateArgument *Args; - unsigned NumArgs; + ArrayRef<TemplateArgument> Args; if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) { const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(TAW->getType()); - Args = TST->getArgs(); - NumArgs = TST->getNumArgs(); + Args = TST->template_arguments(); } else { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - Args = TemplateArgs.data(); - NumArgs = TemplateArgs.size(); + Args = TemplateArgs.asArray(); } IncludeStrongLifetimeRAII Strong(Policy); - TemplateSpecializationType::PrintTemplateArgumentList(OS, - Args, NumArgs, - Policy); + TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, Policy); } spaceBeforePlaceHolder(OS); @@ -1040,11 +1069,9 @@ void TypePrinter::printTemplateSpecializationBefore( raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); T->getTemplateName().print(OS, Policy); - - TemplateSpecializationType::PrintTemplateArgumentList(OS, - T->getArgs(), - T->getNumArgs(), - Policy); + + TemplateSpecializationType::PrintTemplateArgumentList( + OS, T->template_arguments(), Policy); spaceBeforePlaceHolder(OS); } void TypePrinter::printTemplateSpecializationAfter( @@ -1060,14 +1087,16 @@ void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T, void TypePrinter::printElaboratedBefore(const ElaboratedType *T, raw_ostream &OS) { - if (Policy.SuppressTag && isa<TagType>(T->getNamedType())) - return; - OS << TypeWithKeyword::getKeywordName(T->getKeyword()); - if (T->getKeyword() != ETK_None) - OS << " "; - NestedNameSpecifier* Qualifier = T->getQualifier(); - if (Qualifier) - Qualifier->print(OS, Policy); + // The tag definition will take care of these. + if (!Policy.IncludeTagDefinition) + { + OS << TypeWithKeyword::getKeywordName(T->getKeyword()); + if (T->getKeyword() != ETK_None) + OS << " "; + NestedNameSpecifier* Qualifier = T->getQualifier(); + if (Qualifier) + Qualifier->print(OS, Policy); + } ElaboratedTypePolicyRAII PolicyRAII(Policy); printBefore(T->getNamedType(), OS); @@ -1119,8 +1148,7 @@ void TypePrinter::printDependentTemplateSpecializationBefore( T->getQualifier()->print(OS, Policy); OS << T->getIdentifier()->getName(); TemplateSpecializationType::PrintTemplateArgumentList(OS, - T->getArgs(), - T->getNumArgs(), + T->template_arguments(), Policy); spaceBeforePlaceHolder(OS); } @@ -1305,6 +1333,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case AttributedType::attr_fastcall: OS << "fastcall"; break; case AttributedType::attr_stdcall: OS << "stdcall"; break; case AttributedType::attr_thiscall: OS << "thiscall"; break; + case AttributedType::attr_swiftcall: OS << "swiftcall"; break; case AttributedType::attr_vectorcall: OS << "vectorcall"; break; case AttributedType::attr_pascal: OS << "pascal"; break; case AttributedType::attr_ms_abi: OS << "ms_abi"; break; @@ -1321,6 +1350,12 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, break; } case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break; + case AttributedType::attr_preserve_most: + OS << "preserve_most"; + break; + case AttributedType::attr_preserve_all: + OS << "preserve_all"; + break; } OS << "))"; } @@ -1400,50 +1435,46 @@ void TemplateSpecializationType:: const TemplateArgumentListInfo &Args, const PrintingPolicy &Policy) { return PrintTemplateArgumentList(OS, - Args.getArgumentArray(), - Args.size(), + Args.arguments(), Policy); } -void -TemplateSpecializationType::PrintTemplateArgumentList( - raw_ostream &OS, - const TemplateArgument *Args, - unsigned NumArgs, - const PrintingPolicy &Policy, - bool SkipBrackets) { +void TemplateSpecializationType::PrintTemplateArgumentList( + raw_ostream &OS, ArrayRef<TemplateArgument> Args, + const PrintingPolicy &Policy, bool SkipBrackets) { const char *Comma = Policy.MSVCFormatting ? "," : ", "; if (!SkipBrackets) OS << '<'; - + bool needSpace = false; - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { + bool FirstArg = true; + for (const TemplateArgument &Arg : Args) { // Print the argument into a string. SmallString<128> Buf; llvm::raw_svector_ostream ArgOS(Buf); - if (Args[Arg].getKind() == TemplateArgument::Pack) { - if (Args[Arg].pack_size() && Arg > 0) + if (Arg.getKind() == TemplateArgument::Pack) { + if (Arg.pack_size() && !FirstArg) OS << Comma; PrintTemplateArgumentList(ArgOS, - Args[Arg].pack_begin(), - Args[Arg].pack_size(), + Arg.getPackAsArray(), Policy, true); } else { - if (Arg > 0) + if (!FirstArg) OS << Comma; - Args[Arg].print(Policy, ArgOS); + Arg.print(Policy, ArgOS); } StringRef ArgString = ArgOS.str(); // If this is the first argument and its string representation // begins with the global scope specifier ('::foo'), add a space // to avoid printing the diagraph '<:'. - if (!Arg && !ArgString.empty() && ArgString[0] == ':') + if (FirstArg && !ArgString.empty() && ArgString[0] == ':') OS << ' '; OS << ArgString; needSpace = (!ArgString.empty() && ArgString.back() == '>'); + FirstArg = false; } // If the last character of our string is '>', add another space to @@ -1459,40 +1490,41 @@ TemplateSpecializationType::PrintTemplateArgumentList( // Sadly, repeat all that with TemplateArgLoc. void TemplateSpecializationType:: PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgumentLoc *Args, unsigned NumArgs, + ArrayRef<TemplateArgumentLoc> Args, const PrintingPolicy &Policy) { OS << '<'; const char *Comma = Policy.MSVCFormatting ? "," : ", "; bool needSpace = false; - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - if (Arg > 0) + bool FirstArg = true; + for (const TemplateArgumentLoc &Arg : Args) { + if (!FirstArg) OS << Comma; - + // Print the argument into a string. SmallString<128> Buf; llvm::raw_svector_ostream ArgOS(Buf); - if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) { + if (Arg.getArgument().getKind() == TemplateArgument::Pack) { PrintTemplateArgumentList(ArgOS, - Args[Arg].getArgument().pack_begin(), - Args[Arg].getArgument().pack_size(), + Arg.getArgument().getPackAsArray(), Policy, true); } else { - Args[Arg].getArgument().print(Policy, ArgOS); + Arg.getArgument().print(Policy, ArgOS); } StringRef ArgString = ArgOS.str(); - + // If this is the first argument and its string representation // begins with the global scope specifier ('::foo'), add a space // to avoid printing the diagraph '<:'. - if (!Arg && !ArgString.empty() && ArgString[0] == ':') + if (FirstArg && !ArgString.empty() && ArgString[0] == ':') OS << ' '; OS << ArgString; needSpace = (!ArgString.empty() && ArgString.back() == '>'); + FirstArg = false; } - + // If the last character of our string is '>', add another space to // keep the two '>''s separate tokens. We don't *have* to do this in // C++0x, but it's still good hygiene. @@ -1543,7 +1575,13 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, unsigned quals = getCVRQualifiers(); if (quals) { - AppendTypeQualList(OS, quals, Policy.LangOpts.C99); + AppendTypeQualList(OS, quals, Policy.Restrict); + addSpace = true; + } + if (hasUnaligned()) { + if (addSpace) + OS << ' '; + OS << "__unaligned"; addSpace = true; } if (unsigned addrspace = getAddressSpace()) { @@ -1617,11 +1655,11 @@ std::string QualType::getAsString(const Type *ty, Qualifiers qs) { void QualType::print(const Type *ty, Qualifiers qs, raw_ostream &OS, const PrintingPolicy &policy, - const Twine &PlaceHolder) { + const Twine &PlaceHolder, unsigned Indentation) { SmallString<128> PHBuf; StringRef PH = PlaceHolder.toStringRef(PHBuf); - TypePrinter(policy).print(ty, qs, OS, PH); + TypePrinter(policy, Indentation).print(ty, qs, OS, PH); } void QualType::getAsStringInternal(const Type *ty, Qualifiers qs, diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp index bae018652f91..640fbf47aeab 100644 --- a/lib/AST/VTableBuilder.cpp +++ b/lib/AST/VTableBuilder.cpp @@ -2416,7 +2416,7 @@ private: MethodVFTableLocationsTy MethodVFTableLocations; /// \brief Does this class have an RTTI component? - bool HasRTTIComponent; + bool HasRTTIComponent = false; /// MethodInfo - Contains information about a method in a vtable. /// (Used for computing 'this' pointer adjustment thunks. @@ -2545,12 +2545,13 @@ public: MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)), WhichVFPtr(*Which), Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) { - // Only include the RTTI component if we know that we will provide a - // definition of the vftable. - HasRTTIComponent = Context.getLangOpts().RTTIData && - !MostDerivedClass->hasAttr<DLLImportAttr>() && - MostDerivedClass->getTemplateSpecializationKind() != - TSK_ExplicitInstantiationDeclaration; + // Provide the RTTI component if RTTIData is enabled. If the vftable would + // be available externally, we should not provide the RTTI componenent. It + // is currently impossible to get available externally vftables with either + // dllimport or extern template instantiations, but eventually we may add a + // flag to support additional devirtualization that needs this. + if (Context.getLangOpts().RTTIData) + HasRTTIComponent = true; LayoutVFTable(); |