diff options
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 584 |
1 files changed, 363 insertions, 221 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 21b6f36e9aa7..0d69eb90abaf 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1,9 +1,8 @@ //===- ASTContext.cpp - Context to hold long-lived AST nodes --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -95,38 +94,18 @@ using namespace clang; -unsigned ASTContext::NumImplicitDefaultConstructors; -unsigned ASTContext::NumImplicitDefaultConstructorsDeclared; -unsigned ASTContext::NumImplicitCopyConstructors; -unsigned ASTContext::NumImplicitCopyConstructorsDeclared; -unsigned ASTContext::NumImplicitMoveConstructors; -unsigned ASTContext::NumImplicitMoveConstructorsDeclared; -unsigned ASTContext::NumImplicitCopyAssignmentOperators; -unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; -unsigned ASTContext::NumImplicitMoveAssignmentOperators; -unsigned ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; -unsigned ASTContext::NumImplicitDestructors; -unsigned ASTContext::NumImplicitDestructorsDeclared; - enum FloatingRank { Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank }; RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { - if (!CommentsLoaded && ExternalSource) { - ExternalSource->ReadComments(); - -#ifndef NDEBUG - ArrayRef<RawComment *> RawComments = Comments.getComments(); - assert(std::is_sorted(RawComments.begin(), RawComments.end(), - BeforeThanCompare<RawComment>(SourceMgr))); -#endif - - CommentsLoaded = true; - } - assert(D); + // If we already tried to load comments but there are none, + // we won't find anything. + if (CommentsLoaded && Comments.getComments().empty()) + return nullptr; + // User can not attach documentation to implicit declarations. if (D->isImplicit()) return nullptr; @@ -176,12 +155,6 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { isa<TemplateTemplateParmDecl>(D)) return nullptr; - ArrayRef<RawComment *> RawComments = Comments.getComments(); - - // If there are no comments anywhere, we won't find anything. - if (RawComments.empty()) - return nullptr; - // Find declaration location. // For Objective-C declarations we generally don't expect to have multiple // declarators, thus use declaration starting location as the "declaration @@ -220,6 +193,23 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { if (DeclLoc.isInvalid() || !DeclLoc.isFileID()) return nullptr; + if (!CommentsLoaded && ExternalSource) { + ExternalSource->ReadComments(); + +#ifndef NDEBUG + ArrayRef<RawComment *> RawComments = Comments.getComments(); + assert(std::is_sorted(RawComments.begin(), RawComments.end(), + BeforeThanCompare<RawComment>(SourceMgr))); +#endif + + CommentsLoaded = true; + } + + ArrayRef<RawComment *> RawComments = Comments.getComments(); + // If there are no comments anywhere, we won't find anything. + if (RawComments.empty()) + return nullptr; + // Find the comment that occurs just after this declaration. ArrayRef<RawComment *>::iterator Comment; { @@ -238,12 +228,11 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { if (Found) { Comment = MaybeBeforeDecl + 1; - assert(Comment == std::lower_bound(RawComments.begin(), RawComments.end(), - &CommentAtDeclLoc, Compare)); + assert(Comment == + llvm::lower_bound(RawComments, &CommentAtDeclLoc, Compare)); } else { // Slow path. - Comment = std::lower_bound(RawComments.begin(), RawComments.end(), - &CommentAtDeclLoc, Compare); + Comment = llvm::lower_bound(RawComments, &CommentAtDeclLoc, Compare); } } @@ -265,6 +254,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { SourceMgr.getLineNumber(DeclLocDecomp.first, DeclLocDecomp.second) == SourceMgr.getLineNumber(CommentBeginDecomp.first, CommentBeginDecomp.second)) { + (**Comment).setAttached(); return *Comment; } } @@ -306,6 +296,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { if (Text.find_first_of(";{}#@") != StringRef::npos) return nullptr; + (**Comment).setAttached(); return *Comment; } @@ -835,6 +826,9 @@ ASTContext::~ASTContext() { for (const auto &Value : ModuleInitializers) Value.second->~PerModuleInitializers(); + + for (APValue *Value : APValueCleanups) + Value->~APValue(); } class ASTContext::ParentMap { @@ -913,7 +907,7 @@ void ASTContext::setTraversalScope(const std::vector<Decl *> &TopLevelDecls) { Parents.reset(); } -void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { +void ASTContext::AddDeallocation(void (*Callback)(void *), void *Data) const { Deallocations.push_back({Callback, Data}); } @@ -1391,24 +1385,6 @@ ASTContext::setTemplateOrSpecializationInfo(VarDecl *Inst, TemplateOrInstantiation[Inst] = TSI; } -FunctionDecl *ASTContext::getClassScopeSpecializationPattern( - const FunctionDecl *FD){ - assert(FD && "Specialization is 0"); - llvm::DenseMap<const FunctionDecl*, FunctionDecl *>::const_iterator Pos - = ClassScopeSpecializationPattern.find(FD); - if (Pos == ClassScopeSpecializationPattern.end()) - return nullptr; - - return Pos->second; -} - -void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD, - FunctionDecl *Pattern) { - assert(FD && "Specialization is 0"); - assert(Pattern && "Class scope specialization pattern is 0"); - ClassScopeSpecializationPattern[FD] = Pattern; -} - NamedDecl * ASTContext::getInstantiatedFromUsingDecl(NamedDecl *UUD) { auto Pos = InstantiatedFromUsingDecl.find(UUD); @@ -1548,8 +1524,14 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { return Target->getHalfFormat(); case BuiltinType::Float: return Target->getFloatFormat(); case BuiltinType::Double: return Target->getDoubleFormat(); - case BuiltinType::LongDouble: return Target->getLongDoubleFormat(); - case BuiltinType::Float128: return Target->getFloat128Format(); + case BuiltinType::LongDouble: + if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice) + return AuxTarget->getLongDoubleFormat(); + return Target->getLongDoubleFormat(); + case BuiltinType::Float128: + if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice) + return AuxTarget->getFloat128Format(); + return Target->getFloat128Format(); } } @@ -1610,8 +1592,10 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { if (BaseT.getQualifiers().hasUnaligned()) Align = Target->getCharWidth(); if (const auto *VD = dyn_cast<VarDecl>(D)) { - if (VD->hasGlobalStorage() && !ForAlignof) - Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); + if (VD->hasGlobalStorage() && !ForAlignof) { + uint64_t TypeSize = getTypeSize(T.getTypePtr()); + Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize)); + } } } @@ -1916,8 +1900,16 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { break; case BuiltinType::Float16: case BuiltinType::Half: - Width = Target->getHalfWidth(); - Align = Target->getHalfAlign(); + if (Target->hasFloat16Type() || !getLangOpts().OpenMP || + !getLangOpts().OpenMPIsDevice) { + Width = Target->getHalfWidth(); + Align = Target->getHalfAlign(); + } else { + assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice && + "Expected OpenMP device compilation."); + Width = AuxTarget->getHalfWidth(); + Align = AuxTarget->getHalfAlign(); + } break; case BuiltinType::Float: Width = Target->getFloatWidth(); @@ -1928,12 +1920,27 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = Target->getDoubleAlign(); break; case BuiltinType::LongDouble: - Width = Target->getLongDoubleWidth(); - Align = Target->getLongDoubleAlign(); + if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice && + (Target->getLongDoubleWidth() != AuxTarget->getLongDoubleWidth() || + Target->getLongDoubleAlign() != AuxTarget->getLongDoubleAlign())) { + Width = AuxTarget->getLongDoubleWidth(); + Align = AuxTarget->getLongDoubleAlign(); + } else { + Width = Target->getLongDoubleWidth(); + Align = Target->getLongDoubleAlign(); + } break; case BuiltinType::Float128: - Width = Target->getFloat128Width(); - Align = Target->getFloat128Align(); + if (Target->hasFloat128Type() || !getLangOpts().OpenMP || + !getLangOpts().OpenMPIsDevice) { + Width = Target->getFloat128Width(); + Align = Target->getFloat128Align(); + } else { + assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice && + "Expected OpenMP device compilation."); + Width = AuxTarget->getFloat128Width(); + Align = AuxTarget->getFloat128Align(); + } break; case BuiltinType::NullPtr: Width = Target->getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t) @@ -2057,6 +2064,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Paren: return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr()); + case Type::MacroQualified: + return getTypeInfo( + cast<MacroQualifiedType>(T)->getUnderlyingType().getTypePtr()); + case Type::ObjCTypeParam: return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr()); @@ -2134,7 +2145,7 @@ unsigned ASTContext::getTypeUnadjustedAlign(const Type *T) const { const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); UnadjustedAlign = toBits(Layout.getUnadjustedAlignment()); } else { - UnadjustedAlign = getTypeAlign(T); + UnadjustedAlign = getTypeAlign(T->getUnqualifiedDesugaredType()); } MemoizedUnadjustedAlign[T] = UnadjustedAlign; @@ -2233,7 +2244,8 @@ unsigned ASTContext::getTargetDefaultAlignForAttributeAligned() const { /// getAlignOfGlobalVar - Return the alignment in bits that should be given /// to a global variable of the specified type. unsigned ASTContext::getAlignOfGlobalVar(QualType T) const { - return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign()); + uint64_t TypeSize = getTypeSize(T.getTypePtr()); + return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign(TypeSize)); } /// getAlignOfGlobalVarInChars - Return the alignment in characters that @@ -2574,7 +2586,7 @@ ASTContext::getBlockVarCopyInit(const VarDecl*VD) const { return {nullptr, false}; } -/// Set the copy inialization expression of a block var decl. +/// Set the copy initialization expression of a block var decl. void ASTContext::setBlockVarCopyInit(const VarDecl*VD, Expr *CopyExpr, bool CanThrow) { assert(VD && CopyExpr && "Passed null params"); @@ -2763,6 +2775,12 @@ QualType ASTContext::getFunctionTypeWithExceptionSpec( return getParenType( getFunctionTypeWithExceptionSpec(PT->getInnerType(), ESI)); + // Might be wrapped in a macro qualified type. + if (const auto *MQT = dyn_cast<MacroQualifiedType>(Orig)) + return getMacroQualifiedType( + getFunctionTypeWithExceptionSpec(MQT->getUnderlyingType(), ESI), + MQT->getMacroIdentifier()); + // Might have a calling-convention attribute. if (const auto *AT = dyn_cast<AttributedType>(Orig)) return getAttributedType( @@ -2772,7 +2790,7 @@ QualType ASTContext::getFunctionTypeWithExceptionSpec( // Anything else must be a function type. Rebuild it with the new exception // specification. - const auto *Proto = cast<FunctionProtoType>(Orig); + const auto *Proto = Orig->getAs<FunctionProtoType>(); return getFunctionType( Proto->getReturnType(), Proto->getParamTypes(), Proto->getExtProtoInfo().withExceptionSpec(ESI)); @@ -3739,7 +3757,10 @@ QualType ASTContext::getFunctionTypeInternal( break; } - case EST_DynamicNone: case EST_BasicNoexcept: case EST_NoexceptTrue: + case EST_DynamicNone: + case EST_BasicNoexcept: + case EST_NoexceptTrue: + case EST_NoThrow: CanonicalEPI.ExceptionSpec.Type = EST_BasicNoexcept; break; @@ -3938,7 +3959,7 @@ QualType ASTContext::getAttributedType(attr::Kind attrKind, QualType canon = getCanonicalType(equivalentType); type = new (*this, TypeAlignment) - AttributedType(canon, attrKind, modifiedType, equivalentType); + AttributedType(canon, attrKind, modifiedType, equivalentType); Types.push_back(type); AttributedTypes.InsertNode(type, insertPos); @@ -4219,6 +4240,19 @@ ASTContext::getParenType(QualType InnerType) const { return QualType(T, 0); } +QualType +ASTContext::getMacroQualifiedType(QualType UnderlyingTy, + const IdentifierInfo *MacroII) const { + QualType Canon = UnderlyingTy; + if (!Canon.isCanonical()) + Canon = getCanonicalType(UnderlyingTy); + + auto *newType = new (*this, TypeAlignment) + MacroQualifiedType(UnderlyingTy, Canon, MacroII); + Types.push_back(newType); + return QualType(newType, 0); +} + QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, @@ -4356,7 +4390,13 @@ QualType ASTContext::getPackExpansionType(QualType Pattern, llvm::FoldingSetNodeID ID; PackExpansionType::Profile(ID, Pattern, NumExpansions); - assert(Pattern->containsUnexpandedParameterPack() && + // A deduced type can deduce to a pack, eg + // auto ...x = some_pack; + // That declaration isn't (yet) valid, but is created as part of building an + // init-capture pack: + // [...x = some_pack] {} + assert((Pattern->containsUnexpandedParameterPack() || + Pattern->getContainedDeducedType()) && "Pack expansions must expand one or more parameter packs"); void *InsertPos = nullptr; PackExpansionType *T @@ -4856,19 +4896,20 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType, /// deduced to the given type, or to the canonical undeduced 'auto' type, or the /// canonical deduced-but-dependent 'auto' type. QualType ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, - bool IsDependent) const { + bool IsDependent, bool IsPack) const { + assert((!IsPack || IsDependent) && "only use IsPack for a dependent pack"); if (DeducedType.isNull() && Keyword == AutoTypeKeyword::Auto && !IsDependent) return getAutoDeductType(); // Look in the folding set for an existing type. void *InsertPos = nullptr; llvm::FoldingSetNodeID ID; - AutoType::Profile(ID, DeducedType, Keyword, IsDependent); + AutoType::Profile(ID, DeducedType, Keyword, IsDependent, IsPack); if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(AT, 0); auto *AT = new (*this, TypeAlignment) - AutoType(DeducedType, Keyword, IsDependent); + AutoType(DeducedType, Keyword, IsDependent, IsPack); Types.push_back(AT); if (InsertPos) AutoTypes.InsertNode(AT, InsertPos); @@ -4930,7 +4971,7 @@ QualType ASTContext::getAutoDeductType() const { if (AutoDeductTy.isNull()) AutoDeductTy = QualType( new (*this, TypeAlignment) AutoType(QualType(), AutoTypeKeyword::Auto, - /*dependent*/false), + /*dependent*/false, /*pack*/false), 0); return AutoDeductTy; } @@ -5218,6 +5259,11 @@ ASTContext::getNameForTemplate(TemplateName Name, return DeclarationNameInfo((*Storage->begin())->getDeclName(), NameLoc); } + case TemplateName::AssumedTemplate: { + AssumedTemplateStorage *Storage = Name.getAsAssumedTemplateName(); + return DeclarationNameInfo(Storage->getDeclName(), NameLoc); + } + case TemplateName::DependentTemplate: { DependentTemplateName *DTN = Name.getAsDependentTemplateName(); DeclarationName DName; @@ -5265,7 +5311,8 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const { } case TemplateName::OverloadedTemplate: - llvm_unreachable("cannot canonicalize overloaded template"); + case TemplateName::AssumedTemplate: + llvm_unreachable("cannot canonicalize unresolved template"); case TemplateName::DependentTemplate: { DependentTemplateName *DTN = Name.getAsDependentTemplateName(); @@ -5609,6 +5656,12 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const { return -1; } +int ASTContext::getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const { + if (&getFloatTypeSemantics(LHS) == &getFloatTypeSemantics(RHS)) + return 0; + return getFloatingTypeOrder(LHS, RHS); +} + /// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1). This /// routine will assert if passed a built-in type that isn't an integer or enum, /// or if it is not canonicalized. @@ -6283,12 +6336,13 @@ void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, // Encode type qualifer, 'in', 'inout', etc. for the parameter. getObjCEncodingForTypeQualifier(QT, S); // Encode parameter type. - getObjCEncodingForTypeImpl(T, S, true, true, nullptr, - true /*OutermostType*/, - false /*EncodingProperty*/, - false /*StructField*/, - Extended /*EncodeBlockParameters*/, - Extended /*EncodeClassNames*/); + ObjCEncOptions Options = ObjCEncOptions() + .setExpandPointedToStructures() + .setExpandStructures() + .setIsOutermostType(); + if (Extended) + Options.setEncodeBlockParameters().setEncodeClassNames(); + getObjCEncodingForTypeImpl(T, S, Options, /*Field=*/nullptr); } /// getObjCEncodingForMethodDecl - Return the encoded type for this method @@ -6480,9 +6534,12 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S, // directly pointed to, and expanding embedded structures. Note that // these rules are sufficient to prevent recursive encoding of the // same type. - getObjCEncodingForTypeImpl(T, S, true, true, Field, - true /* outermost type */, false, false, - false, false, false, NotEncodedT); + getObjCEncodingForTypeImpl(T, S, + ObjCEncOptions() + .setExpandPointedToStructures() + .setExpandStructures() + .setIsOutermostType(), + Field, NotEncodedT); } void ASTContext::getObjCEncodingForPropertyType(QualType T, @@ -6490,9 +6547,13 @@ void ASTContext::getObjCEncodingForPropertyType(QualType T, // Encode result type. // GCC has some special rules regarding encoding of properties which // closely resembles encoding of ivars. - getObjCEncodingForTypeImpl(T, S, true, true, nullptr, - true /* outermost type */, - true /* encoding property */); + getObjCEncodingForTypeImpl(T, S, + ObjCEncOptions() + .setExpandPointedToStructures() + .setExpandStructures() + .setIsOutermostType() + .setEncodingProperty(), + /*Field=*/nullptr); } static char getObjCEncodingForPrimitiveKind(const ASTContext *C, @@ -6639,16 +6700,9 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, } // FIXME: Use SmallString for accumulating string. -void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, - bool ExpandPointedToStructures, - bool ExpandStructures, +void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, + const ObjCEncOptions Options, const FieldDecl *FD, - bool OutermostType, - bool EncodingProperty, - bool StructField, - bool EncodeBlockParameters, - bool EncodeClassNames, - bool EncodePointerToObjCTypedef, QualType *NotEncodedT) const { CanQualType CT = getCanonicalType(T); switch (CT->getTypeClass()) { @@ -6665,14 +6719,16 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::Complex: { const auto *CT = T->castAs<ComplexType>(); S += 'j'; - getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr); + getObjCEncodingForTypeImpl(CT->getElementType(), S, ObjCEncOptions(), + /*Field=*/nullptr); return; } case Type::Atomic: { const auto *AT = T->castAs<AtomicType>(); S += 'A'; - getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr); + getObjCEncodingForTypeImpl(AT->getValueType(), S, ObjCEncOptions(), + /*Field=*/nullptr); return; } @@ -6698,11 +6754,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // the pointer itself gets ignored, _unless_ we are looking at a typedef! // Also, do not emit the 'r' for anything but the outermost type! if (isa<TypedefType>(T.getTypePtr())) { - if (OutermostType && T.isConstQualified()) { + if (Options.IsOutermostType() && T.isConstQualified()) { isReadOnly = true; S += 'r'; } - } else if (OutermostType) { + } else if (Options.IsOutermostType()) { QualType P = PointeeTy; while (P->getAs<PointerType>()) P = P->getAs<PointerType>()->getPointeeType(); @@ -6742,9 +6798,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += '^'; getLegacyIntegralTypeEncoding(PointeeTy); - getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures, - nullptr, false, false, false, false, false, false, - NotEncodedT); + ObjCEncOptions NewOptions; + if (Options.ExpandPointedToStructures()) + NewOptions.setExpandStructures(); + getObjCEncodingForTypeImpl(PointeeTy, S, NewOptions, + /*Field=*/nullptr, NotEncodedT); return; } @@ -6753,12 +6811,13 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::VariableArray: { const auto *AT = cast<ArrayType>(CT); - if (isa<IncompleteArrayType>(AT) && !StructField) { + if (isa<IncompleteArrayType>(AT) && !Options.IsStructField()) { // Incomplete arrays are encoded as a pointer to the array element. S += '^'; - getObjCEncodingForTypeImpl(AT->getElementType(), S, - false, ExpandStructures, FD); + getObjCEncodingForTypeImpl( + AT->getElementType(), S, + Options.keepingOnly(ObjCEncOptions().setExpandStructures()), FD); } else { S += '['; @@ -6771,10 +6830,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += '0'; } - getObjCEncodingForTypeImpl(AT->getElementType(), S, - false, ExpandStructures, FD, - false, false, false, false, false, false, - NotEncodedT); + getObjCEncodingForTypeImpl( + AT->getElementType(), S, + Options.keepingOnly(ObjCEncOptions().setExpandStructures()), FD, + NotEncodedT); S += ']'; } return; @@ -6800,7 +6859,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } else { S += '?'; } - if (ExpandStructures) { + if (Options.ExpandStructures()) { S += '='; if (!RDecl->isUnion()) { getObjCEncodingForStructureImpl(RDecl, S, FD, true, NotEncodedT); @@ -6814,16 +6873,16 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Special case bit-fields. if (Field->isBitField()) { - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, + getObjCEncodingForTypeImpl(Field->getType(), S, + ObjCEncOptions().setExpandStructures(), Field); } else { QualType qt = Field->getType(); getLegacyIntegralTypeEncoding(qt); - getObjCEncodingForTypeImpl(qt, S, false, true, - FD, /*OutermostType*/false, - /*EncodingProperty*/false, - /*StructField*/true, - false, false, false, NotEncodedT); + getObjCEncodingForTypeImpl( + qt, S, + ObjCEncOptions().setExpandStructures().setIsStructField(), FD, + NotEncodedT); } } } @@ -6835,26 +6894,20 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::BlockPointer: { const auto *BT = T->castAs<BlockPointerType>(); S += "@?"; // Unlike a pointer-to-function, which is "^?". - if (EncodeBlockParameters) { + if (Options.EncodeBlockParameters()) { const auto *FT = BT->getPointeeType()->castAs<FunctionType>(); S += '<'; // Block return type - getObjCEncodingForTypeImpl( - FT->getReturnType(), S, ExpandPointedToStructures, ExpandStructures, - FD, false /* OutermostType */, EncodingProperty, - false /* StructField */, EncodeBlockParameters, EncodeClassNames, false, - NotEncodedT); + getObjCEncodingForTypeImpl(FT->getReturnType(), S, + Options.forComponentType(), FD, NotEncodedT); // Block self S += "@?"; // Block parameters if (const auto *FPT = dyn_cast<FunctionProtoType>(FT)) { for (const auto &I : FPT->param_types()) - getObjCEncodingForTypeImpl( - I, S, ExpandPointedToStructures, ExpandStructures, FD, - false /* OutermostType */, EncodingProperty, - false /* StructField */, EncodeBlockParameters, EncodeClassNames, - false, NotEncodedT); + getObjCEncodingForTypeImpl(I, S, Options.forComponentType(), FD, + NotEncodedT); } S += '>'; } @@ -6882,18 +6935,19 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, ObjCInterfaceDecl *OI = T->castAs<ObjCObjectType>()->getInterface(); S += '{'; S += OI->getObjCRuntimeNameAsString(); - if (ExpandStructures) { + if (Options.ExpandStructures()) { S += '='; SmallVector<const ObjCIvarDecl*, 32> Ivars; DeepCollectObjCIvars(OI, true, Ivars); for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { const FieldDecl *Field = Ivars[i]; if (Field->isBitField()) - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); + getObjCEncodingForTypeImpl(Field->getType(), S, + ObjCEncOptions().setExpandStructures(), + Field); else - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD, - false, false, false, false, false, - EncodePointerToObjCTypedef, + getObjCEncodingForTypeImpl(Field->getType(), S, + ObjCEncOptions().setExpandStructures(), FD, NotEncodedT); } } @@ -6910,17 +6964,20 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) { // FIXME: Consider if we need to output qualifiers for 'Class<p>'. - // Since this is a binary compatibility issue, need to consult with runtime - // folks. Fortunately, this is a *very* obscure construct. + // Since this is a binary compatibility issue, need to consult with + // runtime folks. Fortunately, this is a *very* obscure construct. S += '#'; return; } if (OPT->isObjCQualifiedIdType()) { - getObjCEncodingForTypeImpl(getObjCIdType(), S, - ExpandPointedToStructures, - ExpandStructures, FD); - if (FD || EncodingProperty || EncodeClassNames) { + getObjCEncodingForTypeImpl( + getObjCIdType(), S, + Options.keepingOnly(ObjCEncOptions() + .setExpandPointedToStructures() + .setExpandStructures()), + FD); + if (FD || Options.EncodingProperty() || Options.EncodeClassNames()) { // Note that we do extended encoding of protocol qualifer list // Only when doing ivar or property encoding. S += '"'; @@ -6934,39 +6991,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } - QualType PointeeTy = OPT->getPointeeType(); - if (!EncodingProperty && - isa<TypedefType>(PointeeTy.getTypePtr()) && - !EncodePointerToObjCTypedef) { - // Another historical/compatibility reason. - // We encode the underlying type which comes out as - // {...}; - S += '^'; - if (FD && OPT->getInterfaceDecl()) { - // Prevent recursive encoding of fields in some rare cases. - ObjCInterfaceDecl *OI = OPT->getInterfaceDecl(); - SmallVector<const ObjCIvarDecl*, 32> Ivars; - DeepCollectObjCIvars(OI, true, Ivars); - for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { - if (Ivars[i] == FD) { - S += '{'; - S += OI->getObjCRuntimeNameAsString(); - S += '}'; - return; - } - } - } - getObjCEncodingForTypeImpl(PointeeTy, S, - false, ExpandPointedToStructures, - nullptr, - false, false, false, false, false, - /*EncodePointerToObjCTypedef*/true); - return; - } - S += '@'; if (OPT->getInterfaceDecl() && - (FD || EncodingProperty || EncodeClassNames)) { + (FD || Options.EncodingProperty() || Options.EncodeClassNames())) { S += '"'; S += OPT->getInterfaceDecl()->getObjCRuntimeNameAsString(); for (const auto *I : OPT->quals()) { @@ -6980,7 +7007,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } // gcc just blithely ignores member pointers. - // FIXME: we shoul do better than that. 'M' is available. + // FIXME: we should do better than that. 'M' is available. case Type::MemberPointer: // This matches gcc's encoding, even though technically it is insufficient. //FIXME. We should do a better job than gcc. @@ -7142,11 +7169,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, } else { QualType qt = field->getType(); getLegacyIntegralTypeEncoding(qt); - getObjCEncodingForTypeImpl(qt, S, false, true, FD, - /*OutermostType*/false, - /*EncodingProperty*/false, - /*StructField*/true, - false, false, false, NotEncodedT); + getObjCEncodingForTypeImpl( + qt, S, ObjCEncOptions().setExpandStructures().setIsStructField(), + FD, NotEncodedT); #ifndef NDEBUG CurOffs += getTypeSize(field->getType()); #endif @@ -7606,6 +7631,13 @@ ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin, return TemplateName(OT); } +/// Retrieve a template name representing an unqualified-id that has been +/// assumed to name a template for ADL purposes. +TemplateName ASTContext::getAssumedTemplateName(DeclarationName Name) const { + auto *OT = new (*this) AssumedTemplateStorage(Name); + return TemplateName(OT); +} + /// Retrieve the template name that represents a qualified /// template name such as \c std::vector. TemplateName @@ -8581,7 +8613,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lproto->isVariadic() != rproto->isVariadic()) return {}; - if (lproto->getTypeQuals() != rproto->getTypeQuals()) + if (lproto->getMethodQuals() != rproto->getMethodQuals()) return {}; SmallVector<FunctionProtoType::ExtParameterInfo, 4> newParamInfos; @@ -9246,7 +9278,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, // Read the prefixed modifiers first. bool Done = false; #ifndef NDEBUG - bool IsSpecialLong = false; + bool IsSpecial = false; #endif while (!Done) { switch (*Str++) { @@ -9265,26 +9297,26 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, Unsigned = true; break; case 'L': - assert(!IsSpecialLong && "Can't use 'L' with 'W' or 'N' modifiers"); + assert(!IsSpecial && "Can't use 'L' with 'W', 'N', 'Z' or 'O' modifiers"); assert(HowLong <= 2 && "Can't have LLLL modifier"); ++HowLong; break; case 'N': // 'N' behaves like 'L' for all non LP64 targets and 'int' otherwise. - assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!"); + assert(!IsSpecial && "Can't use two 'N', 'W', 'Z' or 'O' modifiers!"); assert(HowLong == 0 && "Can't use both 'L' and 'N' modifiers!"); #ifndef NDEBUG - IsSpecialLong = true; + IsSpecial = true; #endif if (Context.getTargetInfo().getLongWidth() == 32) ++HowLong; break; case 'W': // This modifier represents int64 type. - assert(!IsSpecialLong && "Can't use two 'N' or 'W' modifiers!"); + assert(!IsSpecial && "Can't use two 'N', 'W', 'Z' or 'O' modifiers!"); assert(HowLong == 0 && "Can't use both 'L' and 'W' modifiers!"); #ifndef NDEBUG - IsSpecialLong = true; + IsSpecial = true; #endif switch (Context.getTargetInfo().getInt64Type()) { default: @@ -9297,6 +9329,38 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, break; } break; + case 'Z': + // This modifier represents int32 type. + assert(!IsSpecial && "Can't use two 'N', 'W', 'Z' or 'O' modifiers!"); + assert(HowLong == 0 && "Can't use both 'L' and 'Z' modifiers!"); + #ifndef NDEBUG + IsSpecial = true; + #endif + switch (Context.getTargetInfo().getIntTypeByWidth(32, true)) { + default: + llvm_unreachable("Unexpected integer type"); + case TargetInfo::SignedInt: + HowLong = 0; + break; + case TargetInfo::SignedLong: + HowLong = 1; + break; + case TargetInfo::SignedLongLong: + HowLong = 2; + break; + } + break; + case 'O': + assert(!IsSpecial && "Can't use two 'N', 'W', 'Z' or 'O' modifiers!"); + assert(HowLong == 0 && "Can't use both 'L' and 'O' modifiers!"); + #ifndef NDEBUG + IsSpecial = true; + #endif + if (Context.getLangOpts().OpenCL) + HowLong = 1; + else + HowLong = 2; + break; } } @@ -9518,6 +9582,10 @@ QualType ASTContext::GetBuiltinType(unsigned Id, GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs) const { const char *TypeStr = BuiltinInfo.getTypeString(Id); + if (TypeStr[0] == '\0') { + Error = GE_Missing_type; + return {}; + } SmallVector<QualType, 8> ArgTypes; @@ -9553,10 +9621,12 @@ QualType ASTContext::GetBuiltinType(unsigned Id, assert((TypeStr[0] != '.' || TypeStr[1] == 0) && "'.' should only occur at end of builtin type list!"); - FunctionType::ExtInfo EI(CC_C); + bool Variadic = (TypeStr[0] == '.'); + + FunctionType::ExtInfo EI(getDefaultCallingConvention( + Variadic, /*IsCXXMethod=*/false, /*IsBuiltin=*/true)); if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true); - bool Variadic = (TypeStr[0] == '.'); // We really shouldn't be making a no-proto type here. if (ArgTypes.empty() && Variadic && !getLangOpts().CPlusPlus) @@ -9784,12 +9854,12 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return false; } else if (isa<PragmaCommentDecl>(D)) return true; - else if (isa<OMPThreadPrivateDecl>(D)) - return true; else if (isa<PragmaDetectMismatchDecl>(D)) return true; else if (isa<OMPThreadPrivateDecl>(D)) return !D->getDeclContext()->isDependentContext(); + else if (isa<OMPAllocateDecl>(D)) + return !D->getDeclContext()->isDependentContext(); else if (isa<OMPDeclareReductionDecl>(D)) return !D->getDeclContext()->isDependentContext(); else if (isa<ImportDecl>(D)) @@ -9931,34 +10001,39 @@ void ASTContext::forEachMultiversionedFunctionVersion( } CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, - bool IsCXXMethod) const { + bool IsCXXMethod, + bool IsBuiltin) const { // Pass through to the C++ ABI object if (IsCXXMethod) return ABI->getDefaultMethodCallConv(IsVariadic); - switch (LangOpts.getDefaultCallingConv()) { - case LangOptions::DCC_None: - break; - case LangOptions::DCC_CDecl: - return CC_C; - case LangOptions::DCC_FastCall: - if (getTargetInfo().hasFeature("sse2") && !IsVariadic) - 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; - case LangOptions::DCC_RegCall: - // __regcall cannot be applied to variadic functions. - if (!IsVariadic) - return CC_X86RegCall; - break; + // Builtins ignore user-specified default calling convention and remain the + // Target's default calling convention. + if (!IsBuiltin) { + switch (LangOpts.getDefaultCallingConv()) { + case LangOptions::DCC_None: + break; + case LangOptions::DCC_CDecl: + return CC_C; + case LangOptions::DCC_FastCall: + if (getTargetInfo().hasFeature("sse2") && !IsVariadic) + 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; + case LangOptions::DCC_RegCall: + // __regcall cannot be applied to variadic functions. + if (!IsVariadic) + return CC_X86RegCall; + break; + } } return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown); } @@ -9978,8 +10053,10 @@ VTableContextBase *ASTContext::getVTableContext() { return VTContext.get(); } -MangleContext *ASTContext::createMangleContext() { - switch (Target->getCXXABI().getKind()) { +MangleContext *ASTContext::createMangleContext(const TargetInfo *T) { + if (!T) + T = Target; + switch (T->getCXXABI().getKind()) { case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericItanium: case TargetCXXABI::GenericARM: @@ -10010,8 +10087,7 @@ size_t ASTContext::getSideTableAllocatedMemory() const { llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl) + llvm::capacity_in_bytes(OverriddenMethods) + llvm::capacity_in_bytes(Types) + - llvm::capacity_in_bytes(VariableArrayTypes) + - llvm::capacity_in_bytes(ClassScopeSpecializationPattern); + llvm::capacity_in_bytes(VariableArrayTypes); } /// getIntTypeForBitwidth - @@ -10140,6 +10216,31 @@ ASTContext::getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, return MaterializedTemporaryValues.lookup(E); } +QualType ASTContext::getStringLiteralArrayType(QualType EltTy, + unsigned Length) const { + // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). + if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) + EltTy = EltTy.withConst(); + + EltTy = adjustStringLiteralBaseType(EltTy); + + // Get an array type for the string, according to C99 6.4.5. This includes + // the null terminator character. + return getConstantArrayType(EltTy, llvm::APInt(32, Length + 1), + ArrayType::Normal, /*IndexTypeQuals*/ 0); +} + +StringLiteral * +ASTContext::getPredefinedStringLiteralFromCache(StringRef Key) const { + StringLiteral *&Result = StringLiteralCache[Key]; + if (!Result) + Result = StringLiteral::Create( + *this, Key, StringLiteral::Ascii, + /*Pascal*/ false, getStringLiteralArrayType(CharTy, Key.size()), + SourceLocation()); + return Result; +} + bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { const llvm::Triple &T = getTargetInfo().getTriple(); if (!T.isOSDarwin()) @@ -10485,7 +10586,13 @@ unsigned char ASTContext::getFixedPointIBits(QualType Ty) const { } FixedPointSemantics ASTContext::getFixedPointSemantics(QualType Ty) const { - assert(Ty->isFixedPointType()); + assert((Ty->isFixedPointType() || Ty->isIntegerType()) && + "Can only get the fixed point semantics for a " + "fixed point or integer type."); + if (Ty->isIntegerType()) + return FixedPointSemantics::GetIntegerSemantics(getIntWidth(Ty), + Ty->isSignedIntegerType()); + bool isSigned = Ty->isSignedFixedPointType(); return FixedPointSemantics( static_cast<unsigned>(getTypeSize(Ty)), getFixedPointScale(Ty), isSigned, @@ -10502,3 +10609,38 @@ APFixedPoint ASTContext::getFixedPointMin(QualType Ty) const { assert(Ty->isFixedPointType()); return APFixedPoint::getMin(getFixedPointSemantics(Ty)); } + +QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const { + assert(Ty->isUnsignedFixedPointType() && + "Expected unsigned fixed point type"); + const auto *BTy = Ty->getAs<BuiltinType>(); + + switch (BTy->getKind()) { + case BuiltinType::UShortAccum: + return ShortAccumTy; + case BuiltinType::UAccum: + return AccumTy; + case BuiltinType::ULongAccum: + return LongAccumTy; + case BuiltinType::SatUShortAccum: + return SatShortAccumTy; + case BuiltinType::SatUAccum: + return SatAccumTy; + case BuiltinType::SatULongAccum: + return SatLongAccumTy; + case BuiltinType::UShortFract: + return ShortFractTy; + case BuiltinType::UFract: + return FractTy; + case BuiltinType::ULongFract: + return LongFractTy; + case BuiltinType::SatUShortFract: + return SatShortFractTy; + case BuiltinType::SatUFract: + return SatFractTy; + case BuiltinType::SatULongFract: + return SatLongFractTy; + default: + llvm_unreachable("Unexpected unsigned fixed point type"); + } +} |