diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/ASTContext.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/ASTContext.cpp | 626 |
1 files changed, 508 insertions, 118 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 6aad4d1..b531a66 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -34,7 +34,6 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Capacity.h" @@ -652,6 +651,10 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( cast<TemplateTemplateParmDecl>(*P))); } + assert(!TTP->getRequiresClause() && + "Unexpected requires-clause on template template-parameter"); + Expr *const CanonRequiresClause = nullptr; + TemplateTemplateParmDecl *CanonTTP = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(), SourceLocation(), TTP->getDepth(), @@ -661,7 +664,8 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(), CanonParams, - SourceLocation())); + SourceLocation(), + CanonRequiresClause)); // Get the new insert position for the node we care about. Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); @@ -700,8 +704,8 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, // language-specific address space. static const unsigned FakeAddrSpaceMap[] = { 1, // opencl_global - 2, // opencl_local - 3, // opencl_constant + 3, // opencl_local + 2, // opencl_constant 4, // opencl_generic 5, // cuda_device 6, // cuda_constant @@ -788,7 +792,8 @@ ASTContext::~ASTContext() { MaterializedTemporaryValues) MTVPair.second->~APValue(); - llvm::DeleteContainerSeconds(MangleNumberingContexts); + for (const auto &Value : ModuleInitializers) + Value.second->~PerModuleInitializers(); } void ASTContext::ReleaseParentMapEntries() { @@ -902,6 +907,67 @@ void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) { Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end()); } +void ASTContext::PerModuleInitializers::resolve(ASTContext &Ctx) { + if (LazyInitializers.empty()) + return; + + auto *Source = Ctx.getExternalSource(); + assert(Source && "lazy initializers but no external source"); + + auto LazyInits = std::move(LazyInitializers); + LazyInitializers.clear(); + + for (auto ID : LazyInits) + Initializers.push_back(Source->GetExternalDecl(ID)); + + assert(LazyInitializers.empty() && + "GetExternalDecl for lazy module initializer added more inits"); +} + +void ASTContext::addModuleInitializer(Module *M, Decl *D) { + // One special case: if we add a module initializer that imports another + // module, and that module's only initializer is an ImportDecl, simplify. + if (auto *ID = dyn_cast<ImportDecl>(D)) { + auto It = ModuleInitializers.find(ID->getImportedModule()); + + // Maybe the ImportDecl does nothing at all. (Common case.) + if (It == ModuleInitializers.end()) + return; + + // Maybe the ImportDecl only imports another ImportDecl. + auto &Imported = *It->second; + if (Imported.Initializers.size() + Imported.LazyInitializers.size() == 1) { + Imported.resolve(*this); + auto *OnlyDecl = Imported.Initializers.front(); + if (isa<ImportDecl>(OnlyDecl)) + D = OnlyDecl; + } + } + + auto *&Inits = ModuleInitializers[M]; + if (!Inits) + Inits = new (*this) PerModuleInitializers; + Inits->Initializers.push_back(D); +} + +void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs) { + auto *&Inits = ModuleInitializers[M]; + if (!Inits) + Inits = new (*this) PerModuleInitializers; + Inits->LazyInitializers.insert(Inits->LazyInitializers.end(), + IDs.begin(), IDs.end()); +} + +ArrayRef<Decl*> ASTContext::getModuleInitializers(Module *M) { + auto It = ModuleInitializers.find(M); + if (It == ModuleInitializers.end()) + return None; + + auto *Inits = It->second; + Inits->resolve(*this); + return Inits->Initializers; +} + ExternCContextDecl *ASTContext::getExternCContextDecl() const { if (!ExternCContext) ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl()); @@ -1204,9 +1270,8 @@ void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD, } NamedDecl * -ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { - llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos - = InstantiatedFromUsingDecl.find(UUD); +ASTContext::getInstantiatedFromUsingDecl(NamedDecl *UUD) { + auto Pos = InstantiatedFromUsingDecl.find(UUD); if (Pos == InstantiatedFromUsingDecl.end()) return nullptr; @@ -1214,11 +1279,15 @@ ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { } void -ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) { +ASTContext::setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern) { assert((isa<UsingDecl>(Pattern) || isa<UnresolvedUsingValueDecl>(Pattern) || isa<UnresolvedUsingTypenameDecl>(Pattern)) && "pattern decl is not a using decl"); + assert((isa<UsingDecl>(Inst) || + isa<UnresolvedUsingValueDecl>(Inst) || + isa<UnresolvedUsingTypenameDecl>(Inst)) && + "instantiation did not produce a using decl"); assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists"); InstantiatedFromUsingDecl[Inst] = Pattern; } @@ -1389,7 +1458,9 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { T = getPointerType(RT->getPointeeType()); } QualType BaseT = getBaseElementType(T); - if (!BaseT->isIncompleteType() && !T->isFunctionType()) { + if (T->isFunctionType()) + Align = getTypeInfoImpl(T.getTypePtr()).Align; + else if (!BaseT->isIncompleteType()) { // Adjust alignments of declarations with array type by the // large-array alignment on the target. if (const ArrayType *arrayType = getAsArrayType(T)) { @@ -1504,6 +1575,30 @@ bool ASTContext::isAlignmentRequired(QualType T) const { return isAlignmentRequired(T.getTypePtr()); } +unsigned ASTContext::getTypeAlignIfKnown(QualType T) const { + // An alignment on a typedef overrides anything else. + if (auto *TT = T->getAs<TypedefType>()) + if (unsigned Align = TT->getDecl()->getMaxAlignment()) + return Align; + + // If we have an (array of) complete type, we're done. + T = getBaseElementType(T); + if (!T->isIncompleteType()) + return getTypeAlign(T); + + // If we had an array type, its element type might be a typedef + // type with an alignment attribute. + if (auto *TT = T->getAs<TypedefType>()) + if (unsigned Align = TT->getDecl()->getMaxAlignment()) + return Align; + + // Otherwise, see if the declaration of the type had an attribute. + if (auto *TT = T->getAs<TagType>()) + return TT->getDecl()->getMaxAlignment(); + + return 0; +} + TypeInfo ASTContext::getTypeInfo(const Type *T) const { TypeInfoMap::iterator I = MemoizedTypeInfo.find(T); if (I != MemoizedTypeInfo.end()) @@ -1671,24 +1766,29 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); break; - case BuiltinType::OCLSampler: - // Samplers are modeled as integers. - Width = Target->getIntWidth(); - Align = Target->getIntAlign(); + case BuiltinType::OCLSampler: { + auto AS = getTargetAddressSpace(LangAS::opencl_constant); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); break; + } case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: -#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); break; +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: +#include "clang/Basic/OpenCLImageTypes.def" + { + auto AS = getTargetAddressSpace(Target->getOpenCLImageAddrSpace()); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); + } } break; case Type::ObjCObjectPointer: @@ -1787,6 +1887,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Paren: return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr()); + case Type::ObjCTypeParam: + return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr()); + case Type::Typedef: { const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl(); TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); @@ -2284,6 +2387,14 @@ static QualType getFunctionTypeWithExceptionSpec( Proto->getExtProtoInfo().withExceptionSpec(ESI)); } +bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T, + QualType U) { + return hasSameType(T, U) || + (getLangOpts().CPlusPlus1z && + hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None), + getFunctionTypeWithExceptionSpec(*this, U, EST_None))); +} + void ASTContext::adjustExceptionSpec( FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI, bool AsWritten) { @@ -3039,46 +3150,160 @@ ASTContext::getCanonicalFunctionResultType(QualType ResultType) const { return CanResultType; } -QualType -ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, - const FunctionProtoType::ExtProtoInfo &EPI) const { +static bool isCanonicalExceptionSpecification( + const FunctionProtoType::ExceptionSpecInfo &ESI, bool NoexceptInType) { + if (ESI.Type == EST_None) + return true; + if (!NoexceptInType) + return false; + + // C++17 onwards: exception specification is part of the type, as a simple + // boolean "can this function type throw". + if (ESI.Type == EST_BasicNoexcept) + return true; + + // A dynamic exception specification is canonical if it only contains pack + // expansions (so we can't tell whether it's non-throwing) and all its + // contained types are canonical. + if (ESI.Type == EST_Dynamic) { + bool AnyPackExpansions = false; + for (QualType ET : ESI.Exceptions) { + if (!ET.isCanonical()) + return false; + if (ET->getAs<PackExpansionType>()) + AnyPackExpansions = true; + } + return AnyPackExpansions; + } + + // A noexcept(expr) specification is (possibly) canonical if expr is + // value-dependent. + if (ESI.Type == EST_ComputedNoexcept) + return ESI.NoexceptExpr && ESI.NoexceptExpr->isValueDependent(); + + return false; +} + +QualType ASTContext::getFunctionTypeInternal( + QualType ResultTy, ArrayRef<QualType> ArgArray, + const FunctionProtoType::ExtProtoInfo &EPI, bool OnlyWantCanonical) const { size_t NumArgs = ArgArray.size(); // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI, - *this); + *this, true); + + QualType Canonical; + bool Unique = false; void *InsertPos = nullptr; - if (FunctionProtoType *FTP = - FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(FTP, 0); + if (FunctionProtoType *FPT = + FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) { + QualType Existing = QualType(FPT, 0); + + // If we find a pre-existing equivalent FunctionProtoType, we can just reuse + // it so long as our exception specification doesn't contain a dependent + // noexcept expression, or we're just looking for a canonical type. + // Otherwise, we're going to need to create a type + // sugar node to hold the concrete expression. + if (OnlyWantCanonical || EPI.ExceptionSpec.Type != EST_ComputedNoexcept || + EPI.ExceptionSpec.NoexceptExpr == FPT->getNoexceptExpr()) + return Existing; + + // We need a new type sugar node for this one, to hold the new noexcept + // expression. We do no canonicalization here, but that's OK since we don't + // expect to see the same noexcept expression much more than once. + Canonical = getCanonicalType(Existing); + Unique = true; + } + + bool NoexceptInType = getLangOpts().CPlusPlus1z; + bool IsCanonicalExceptionSpec = + isCanonicalExceptionSpecification(EPI.ExceptionSpec, NoexceptInType); // Determine whether the type being created is already canonical or not. - bool isCanonical = - EPI.ExceptionSpec.Type == EST_None && isCanonicalResultType(ResultTy) && - !EPI.HasTrailingReturn; + bool isCanonical = !Unique && IsCanonicalExceptionSpec && + isCanonicalResultType(ResultTy) && !EPI.HasTrailingReturn; for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; - // If this type isn't canonical, get the canonical version of it. - // The exception spec is not part of the canonical type. - QualType Canonical; - if (!isCanonical) { + if (OnlyWantCanonical) + assert(isCanonical && + "given non-canonical parameters constructing canonical type"); + + // If this type isn't canonical, get the canonical version of it if we don't + // already have it. The exception spec is only partially part of the + // canonical type, and only in C++17 onwards. + if (!isCanonical && Canonical.isNull()) { SmallVector<QualType, 16> CanonicalArgs; CanonicalArgs.reserve(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i])); + llvm::SmallVector<QualType, 8> ExceptionTypeStorage; FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI; CanonicalEPI.HasTrailingReturn = false; - CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); + + if (IsCanonicalExceptionSpec) { + // Exception spec is already OK. + } else if (NoexceptInType) { + switch (EPI.ExceptionSpec.Type) { + case EST_Unparsed: case EST_Unevaluated: case EST_Uninstantiated: + // We don't know yet. It shouldn't matter what we pick here; no-one + // should ever look at this. + LLVM_FALLTHROUGH; + case EST_None: case EST_MSAny: + CanonicalEPI.ExceptionSpec.Type = EST_None; + break; + + // A dynamic exception specification is almost always "not noexcept", + // with the exception that a pack expansion might expand to no types. + case EST_Dynamic: { + bool AnyPacks = false; + for (QualType ET : EPI.ExceptionSpec.Exceptions) { + if (ET->getAs<PackExpansionType>()) + AnyPacks = true; + ExceptionTypeStorage.push_back(getCanonicalType(ET)); + } + if (!AnyPacks) + CanonicalEPI.ExceptionSpec.Type = EST_None; + else { + CanonicalEPI.ExceptionSpec.Type = EST_Dynamic; + CanonicalEPI.ExceptionSpec.Exceptions = ExceptionTypeStorage; + } + break; + } + + case EST_DynamicNone: case EST_BasicNoexcept: + CanonicalEPI.ExceptionSpec.Type = EST_BasicNoexcept; + break; + + case EST_ComputedNoexcept: + llvm::APSInt Value(1); + auto *E = CanonicalEPI.ExceptionSpec.NoexceptExpr; + if (!E || !E->isIntegerConstantExpr(Value, *this, nullptr, + /*IsEvaluated*/false)) { + // This noexcept specification is invalid. + // FIXME: Should this be able to happen? + CanonicalEPI.ExceptionSpec.Type = EST_None; + break; + } + + CanonicalEPI.ExceptionSpec.Type = + Value.getBoolValue() ? EST_BasicNoexcept : EST_None; + break; + } + } else { + CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); + } // Adjust the canonical function result type. CanQualType CanResultTy = getCanonicalFunctionResultType(ResultTy); - Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI); + Canonical = + getFunctionTypeInternal(CanResultTy, CanonicalArgs, CanonicalEPI, true); // Get the new insert position for the node we care about. FunctionProtoType *NewIP = @@ -3121,14 +3346,14 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, FunctionProtoType::ExtProtoInfo newEPI = EPI; new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI); Types.push_back(FTP); - FunctionProtoTypes.InsertNode(FTP, InsertPos); + if (!Unique) + FunctionProtoTypes.InsertNode(FTP, InsertPos); return QualType(FTP, 0); } -/// Return pipe type for the specified type. -QualType ASTContext::getPipeType(QualType T) const { +QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const { llvm::FoldingSetNodeID ID; - PipeType::Profile(ID, T); + PipeType::Profile(ID, T, ReadOnly); void *InsertPos = 0; if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos)) @@ -3138,19 +3363,27 @@ QualType ASTContext::getPipeType(QualType T) const { // either, so fill in the canonical type field. QualType Canonical; if (!T.isCanonical()) { - Canonical = getPipeType(getCanonicalType(T)); + Canonical = getPipeType(getCanonicalType(T), ReadOnly); // Get the new insert position for the node we care about. PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical); + PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly); Types.push_back(New); PipeTypes.InsertNode(New, InsertPos); return QualType(New, 0); } +QualType ASTContext::getReadPipeType(QualType T) const { + return getPipeType(T, true); +} + +QualType ASTContext::getWritePipeType(QualType T) const { + return getPipeType(T, false); +} + #ifndef NDEBUG static bool NeedsInjectedClassNameType(const RecordDecl *D) { if (!isa<CXXRecordDecl>(D)) return false; @@ -3641,6 +3874,44 @@ ASTContext::getDependentTemplateSpecializationType( return QualType(T, 0); } +void +ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params, + SmallVectorImpl<TemplateArgument> &Args) { + Args.reserve(Args.size() + Params->size()); + + for (NamedDecl *Param : *Params) { + TemplateArgument Arg; + if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { + QualType ArgType = getTypeDeclType(TTP); + if (TTP->isParameterPack()) + ArgType = getPackExpansionType(ArgType, None); + + Arg = TemplateArgument(ArgType); + } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + Expr *E = new (*this) DeclRefExpr( + NTTP, /*enclosing*/false, + NTTP->getType().getNonLValueExprType(*this), + Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); + + if (NTTP->isParameterPack()) + E = new (*this) PackExpansionExpr(DependentTy, E, NTTP->getLocation(), + None); + Arg = TemplateArgument(E); + } else { + auto *TTP = cast<TemplateTemplateParmDecl>(Param); + if (TTP->isParameterPack()) + Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>()); + else + Arg = TemplateArgument(TemplateName(TTP)); + } + + if (Param->isTemplateParameterPack()) + Arg = TemplateArgument::CreatePackCopy(*this, Arg); + + Args.push_back(Arg); + } +} + QualType ASTContext::getPackExpansionType(QualType Pattern, Optional<unsigned> NumExpansions) { llvm::FoldingSetNodeID ID; @@ -3798,6 +4069,116 @@ QualType ASTContext::getObjCObjectType( return QualType(T, 0); } +/// Apply Objective-C protocol qualifiers to the given type. +/// If this is for the canonical type of a type parameter, we can apply +/// protocol qualifiers on the ObjCObjectPointerType. +QualType +ASTContext::applyObjCProtocolQualifiers(QualType type, + ArrayRef<ObjCProtocolDecl *> protocols, bool &hasError, + bool allowOnPointerType) const { + hasError = false; + + if (const ObjCTypeParamType *objT = + dyn_cast<ObjCTypeParamType>(type.getTypePtr())) { + return getObjCTypeParamType(objT->getDecl(), protocols); + } + + // Apply protocol qualifiers to ObjCObjectPointerType. + if (allowOnPointerType) { + if (const ObjCObjectPointerType *objPtr = + dyn_cast<ObjCObjectPointerType>(type.getTypePtr())) { + const ObjCObjectType *objT = objPtr->getObjectType(); + // Merge protocol lists and construct ObjCObjectType. + SmallVector<ObjCProtocolDecl*, 8> protocolsVec; + protocolsVec.append(objT->qual_begin(), + objT->qual_end()); + protocolsVec.append(protocols.begin(), protocols.end()); + ArrayRef<ObjCProtocolDecl *> protocols = protocolsVec; + type = getObjCObjectType( + objT->getBaseType(), + objT->getTypeArgsAsWritten(), + protocols, + objT->isKindOfTypeAsWritten()); + return getObjCObjectPointerType(type); + } + } + + // Apply protocol qualifiers to ObjCObjectType. + if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){ + // FIXME: Check for protocols to which the class type is already + // known to conform. + + return getObjCObjectType(objT->getBaseType(), + objT->getTypeArgsAsWritten(), + protocols, + objT->isKindOfTypeAsWritten()); + } + + // If the canonical type is ObjCObjectType, ... + if (type->isObjCObjectType()) { + // Silently overwrite any existing protocol qualifiers. + // TODO: determine whether that's the right thing to do. + + // FIXME: Check for protocols to which the class type is already + // known to conform. + return getObjCObjectType(type, { }, protocols, false); + } + + // id<protocol-list> + if (type->isObjCIdType()) { + const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>(); + type = getObjCObjectType(ObjCBuiltinIdTy, { }, protocols, + objPtr->isKindOfType()); + return getObjCObjectPointerType(type); + } + + // Class<protocol-list> + if (type->isObjCClassType()) { + const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>(); + type = getObjCObjectType(ObjCBuiltinClassTy, { }, protocols, + objPtr->isKindOfType()); + return getObjCObjectPointerType(type); + } + + hasError = true; + return type; +} + +QualType +ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl, + ArrayRef<ObjCProtocolDecl *> protocols, + QualType Canonical) const { + // Look in the folding set for an existing type. + llvm::FoldingSetNodeID ID; + ObjCTypeParamType::Profile(ID, Decl, protocols); + void *InsertPos = nullptr; + if (ObjCTypeParamType *TypeParam = + ObjCTypeParamTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(TypeParam, 0); + + if (Canonical.isNull()) { + // We canonicalize to the underlying type. + Canonical = getCanonicalType(Decl->getUnderlyingType()); + if (!protocols.empty()) { + // Apply the protocol qualifers. + bool hasError; + Canonical = applyObjCProtocolQualifiers(Canonical, protocols, hasError, + true/*allowOnPointerType*/); + assert(!hasError && "Error when apply protocol qualifier to bound type"); + } + } + + unsigned size = sizeof(ObjCTypeParamType); + size += protocols.size() * sizeof(ObjCProtocolDecl *); + void *mem = Allocate(size, TypeAlignment); + ObjCTypeParamType *newType = new (mem) + ObjCTypeParamType(Decl, Canonical, protocols); + + Types.push_back(newType); + ObjCTypeParamTypes.InsertNode(newType, InsertPos); + return QualType(newType, 0); +} + /// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's /// protocol list adopt all protocols in QT's qualified-id protocol /// list. @@ -3983,7 +4364,7 @@ QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const { DependentDecltypeType *Canon = DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos); if (!Canon) { - // Build a new, canonical typeof(expr) type. + // Build a new, canonical decltype(expr) type. Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e); DependentDecltypeTypes.InsertNode(Canon, InsertPos); } @@ -4590,7 +4971,15 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) const { QualType PtrTy = getPointerType(PrettyArrayType->getElementType()); // int x[restrict 4] -> int *restrict - return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers()); + QualType Result = getQualifiedType(PtrTy, + PrettyArrayType->getIndexTypeQualifiers()); + + // int x[_Nullable] -> int * _Nullable + if (auto Nullability = Ty->getNullability(*this)) { + Result = const_cast<ASTContext *>(this)->getAttributedType( + AttributedType::getNullabilityAttrKind(*Nullability), Result, Result); + } + return Result; } QualType ASTContext::getBaseElementType(const ArrayType *array) const { @@ -5223,8 +5612,9 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { return S; } -bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, - std::string& S) { +std::string +ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const { + std::string S; // Encode result type. getObjCEncodingForType(Decl->getReturnType(), S); CharUnits ParmOffset; @@ -5235,8 +5625,8 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, if (sz.isZero()) continue; - assert (sz.isPositive() && - "getObjCEncodingForFunctionDecl - Incomplete param type"); + assert(sz.isPositive() && + "getObjCEncodingForFunctionDecl - Incomplete param type"); ParmOffset += sz; } S += charUnitsToString(ParmOffset); @@ -5258,7 +5648,7 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, ParmOffset += getObjCEncodingTypeSize(PType); } - return false; + return S; } /// getObjCEncodingForMethodParameter - Return the encoded type for a single @@ -5280,11 +5670,11 @@ void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. -bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, - std::string& S, - bool Extended) const { +std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, + bool Extended) const { // FIXME: This is not very efficient. // Encode return type. + std::string S; getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(), Decl->getReturnType(), S, Extended); // Compute size of all parameters. @@ -5330,7 +5720,7 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, ParmOffset += getObjCEncodingTypeSize(PType); } - return false; + return S; } ObjCPropertyImplDecl * @@ -5378,9 +5768,9 @@ ASTContext::getObjCPropertyImplDeclForPropertyDecl( /// kPropertyNonAtomic = 'N' // property non-atomic /// }; /// @endcode -void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, - const Decl *Container, - std::string& S) const { +std::string +ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, + const Decl *Container) const { // Collect information from the property implementation decl(s). bool Dynamic = false; ObjCPropertyImplDecl *SynthesizePID = nullptr; @@ -5394,7 +5784,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, } // FIXME: This is not very efficient. - S = "T"; + std::string S = "T"; // Encode result type. // GCC has some special rules regarding encoding of properties which @@ -5443,6 +5833,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, } // FIXME: OBJCGC: weak & strong + return S; } /// getLegacyIntegralTypeEncoding - @@ -5833,18 +6224,20 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, ObjCInterfaceDecl *OI = T->castAs<ObjCObjectType>()->getInterface(); S += '{'; S += OI->getObjCRuntimeNameAsString(); - S += '='; - SmallVector<const ObjCIvarDecl*, 32> Ivars; - DeepCollectObjCIvars(OI, true, Ivars); - for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { - const FieldDecl *Field = cast<FieldDecl>(Ivars[i]); - if (Field->isBitField()) - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); - else - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD, - false, false, false, false, false, - EncodePointerToObjCTypedef, - NotEncodedT); + if (ExpandStructures) { + S += '='; + SmallVector<const ObjCIvarDecl*, 32> Ivars; + DeepCollectObjCIvars(OI, true, Ivars); + for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { + const FieldDecl *Field = cast<FieldDecl>(Ivars[i]); + if (Field->isBitField()) + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); + else + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD, + false, false, false, false, false, + EncodePointerToObjCTypedef, + NotEncodedT); + } } S += '}'; return; @@ -6369,9 +6762,8 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) { // typedef int __builtin_va_list[4]; llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 4); - QualType IntArrayType - = Context->getConstantArrayType(Context->IntTy, - Size, ArrayType::Normal, 0); + QualType IntArrayType = + Context->getConstantArrayType(Context->IntTy, Size, ArrayType::Normal, 0); return Context->buildImplicitTypedef(IntArrayType, "__builtin_va_list"); } @@ -6567,7 +6959,7 @@ ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, QualifiedTemplateName *QTN = QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos); if (!QTN) { - QTN = new (*this, llvm::alignOf<QualifiedTemplateName>()) + QTN = new (*this, alignof(QualifiedTemplateName)) QualifiedTemplateName(NNS, TemplateKeyword, Template); QualifiedTemplateNames.InsertNode(QTN, InsertPos); } @@ -6595,11 +6987,11 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); if (CanonNNS == NNS) { - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Name); } else { TemplateName Canon = getDependentTemplateName(CanonNNS, Name); - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Name, Canon); DependentTemplateName *CheckQTN = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); @@ -6631,13 +7023,13 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); if (CanonNNS == NNS) { - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Operator); } else { TemplateName Canon = getDependentTemplateName(CanonNNS, Operator); - QTN = new (*this, llvm::alignOf<DependentTemplateName>()) + QTN = new (*this, alignof(DependentTemplateName)) DependentTemplateName(NNS, Operator, Canon); - + DependentTemplateName *CheckQTN = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); assert(!CheckQTN && "Dependent template name canonicalization broken"); @@ -7388,7 +7780,7 @@ bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS, bool CompareUnqualified) { if (getLangOpts().CPlusPlus) return hasSameType(LHS, RHS); - + return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull(); } @@ -7902,21 +8294,9 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, } case Type::Pipe: { - // Merge two pointer types, while trying to preserve typedef info - QualType LHSValue = LHS->getAs<PipeType>()->getElementType(); - QualType RHSValue = RHS->getAs<PipeType>()->getElementType(); - if (Unqualified) { - LHSValue = LHSValue.getUnqualifiedType(); - RHSValue = RHSValue.getUnqualifiedType(); - } - QualType ResultType = mergeTypes(LHSValue, RHSValue, false, - Unqualified); - if (ResultType.isNull()) return QualType(); - if (getCanonicalType(LHSValue) == getCanonicalType(ResultType)) - return LHS; - if (getCanonicalType(RHSValue) == getCanonicalType(ResultType)) - return RHS; - return getPipeType(ResultType); + assert(LHS != RHS && + "Equivalent pipe types should have already been handled!"); + return QualType(); } } @@ -8197,6 +8577,10 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!"); Type = Context.getSizeType(); break; + case 'w': // wchar_t. + assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'w'!"); + Type = Context.getWideCharType(); + break; case 'F': Type = Context.getCFConstantStringType(); break; @@ -8385,13 +8769,16 @@ QualType ASTContext::GetBuiltinType(unsigned Id, bool Variadic = (TypeStr[0] == '.'); - // We really shouldn't be making a no-proto type here, especially in C++. - if (ArgTypes.empty() && Variadic) + // We really shouldn't be making a no-proto type here. + if (ArgTypes.empty() && Variadic && !getLangOpts().CPlusPlus) return getFunctionNoProtoType(ResType, EI); FunctionProtoType::ExtProtoInfo EPI; EPI.ExtInfo = EI; EPI.Variadic = Variadic; + if (getLangOpts().CPlusPlus && BuiltinInfo.isNoThrow(Id)) + EPI.ExceptionSpec.Type = + getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone; return getFunctionType(ResType, ArgTypes, EPI); } @@ -8576,6 +8963,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return !D->getDeclContext()->isDependentContext(); else if (isa<OMPDeclareReductionDecl>(D)) return !D->getDeclContext()->isDependentContext(); + else if (isa<ImportDecl>(D)) + return true; else return false; @@ -8613,15 +9002,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { } } - GVALinkage Linkage = GetGVALinkageForFunction(FD); - // static, static inline, always_inline, and extern inline functions can // always be deferred. Normal inline functions can be deferred in C99/C++. // Implicit template instantiations can also be deferred in C++. - if (Linkage == GVA_Internal || Linkage == GVA_AvailableExternally || - Linkage == GVA_DiscardableODR) - return false; - return true; + return !isDiscardableGVALinkage(GetGVALinkageForFunction(FD)); } const VarDecl *VD = cast<VarDecl>(D); @@ -8632,9 +9016,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return false; // Variables that can be needed in other TUs are required. - GVALinkage L = GetGVALinkageForVariable(VD); - if (L != GVA_Internal && L != GVA_AvailableExternally && - L != GVA_DiscardableODR) + if (!isDiscardableGVALinkage(GetGVALinkageForVariable(VD))) return true; // Variables that have destruction with side-effects are required. @@ -8643,9 +9025,18 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // Variables that have initialization with side-effects are required. if (VD->getInit() && VD->getInit()->HasSideEffects(*this) && - !VD->evaluateValue()) + // We can get a value-dependent initializer during error recovery. + (VD->getInit()->isValueDependent() || !VD->evaluateValue())) return true; + // Likewise, variables with tuple-like bindings are required if their + // bindings have side-effects. + if (auto *DD = dyn_cast<DecompositionDecl>(VD)) + for (auto *BD : DD->bindings()) + if (auto *BindingVD = BD->getHoldingVar()) + if (DeclMustBeEmitted(BindingVD)) + return true; + return false; } @@ -8785,13 +9176,14 @@ unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const { MangleNumberingContext & ASTContext::getManglingNumberContext(const DeclContext *DC) { assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C. - MangleNumberingContext *&MCtx = MangleNumberingContexts[DC]; + std::unique_ptr<MangleNumberingContext> &MCtx = MangleNumberingContexts[DC]; if (!MCtx) MCtx = createMangleNumberingContext(); return *MCtx; } -MangleNumberingContext *ASTContext::createMangleNumberingContext() const { +std::unique_ptr<MangleNumberingContext> +ASTContext::createMangleNumberingContext() const { return ABI->createMangleNumberingContext(); } @@ -8808,18 +9200,6 @@ void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD, cast<CXXConstructorDecl>(CD->getFirstDecl())); } -void ASTContext::addDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx, Expr *DAE) { - ABI->addDefaultArgExprForConstructor( - cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx, DAE); -} - -Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, - unsigned ParmIdx) { - return ABI->getDefaultArgExprForConstructor( - cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx); -} - void ASTContext::addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *DD) { return ABI->addTypedefNameForUnnamedTagDecl(TD, DD); @@ -9098,6 +9478,16 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, } +uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const { + unsigned AS; + if (QT->getUnqualifiedDesugaredType()->isNullPtrType()) + AS = 0; + else + AS = QT->getPointeeType().getAddressSpace(); + + return getTargetInfo().getNullPointerValue(AS); +} + // Explicitly instantiate this in case a Redeclarable<T> is used from a TU that // doesn't include ASTContext.h template |