Author: rnk Date: Mon Aug 13 18:55:37 2018 New Revision: 339638 URL: http://llvm.org/viewvc/llvm-project?rev=339638&view=rev Log: Revert r339623 "Model type attributes as regular Attrs."
This breaks compiling atlwin.h in Chromium. I'm sure the code is invalid in some way, but we put a lot of work into accepting it, and I'm sure rejecting it was not an intended consequence of this refactoring. :) Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/AST/Attr.h cfe/trunk/include/clang/AST/Type.h cfe/trunk/include/clang/AST/TypeLoc.h cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/include/clang/Serialization/ASTReader.h cfe/trunk/include/clang/Serialization/ASTWriter.h cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp cfe/trunk/lib/ARCMigrate/Transforms.cpp cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/lib/AST/Type.cpp cfe/trunk/lib/AST/TypeLoc.cpp cfe/trunk/lib/AST/TypePrinter.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/lib/Sema/SemaObjCProperty.cpp cfe/trunk/lib/Sema/SemaType.cpp cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Mon Aug 13 18:55:37 2018 @@ -31,7 +31,6 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/AttrKinds.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" @@ -1423,7 +1422,7 @@ public: QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const; - QualType getAttributedType(attr::Kind attrKind, + QualType getAttributedType(AttributedType::Kind attrKind, QualType modifiedType, QualType equivalentType); Modified: cfe/trunk/include/clang/AST/Attr.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Attr.h (original) +++ cfe/trunk/include/clang/AST/Attr.h Mon Aug 13 18:55:37 2018 @@ -113,19 +113,6 @@ public: void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; }; -class TypeAttr : public Attr { -protected: - TypeAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed) - : Attr(AK, R, SpellingListIndex, IsLateParsed) {} - -public: - static bool classof(const Attr *A) { - return A->getKind() >= attr::FirstTypeAttr && - A->getKind() <= attr::LastTypeAttr; - } -}; - class StmtAttr : public Attr { protected: StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, Modified: cfe/trunk/include/clang/AST/Type.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Type.h (original) +++ cfe/trunk/include/clang/AST/Type.h Mon Aug 13 18:55:37 2018 @@ -21,7 +21,6 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/AttrKinds.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/LLVM.h" @@ -1871,16 +1870,7 @@ public: bool isObjCQualifiedClassType() const; // Class<foo> bool isObjCObjectOrInterfaceType() const; bool isObjCIdType() const; // id - - /// Was this type written with the special inert-in-ARC __unsafe_unretained - /// qualifier? - /// - /// This approximates the answer to the following question: if this - /// translation unit were compiled in ARC, would this type be qualified - /// with __unsafe_unretained? - bool isObjCInertUnsafeUnretainedType() const { - return hasAttr(attr::ObjCInertUnsafeUnretained); - } + bool isObjCInertUnsafeUnretainedType() const; /// Whether the type is Objective-C 'id' or a __kindof type of an /// object type, e.g., __kindof NSView * or __kindof id @@ -2094,10 +2084,6 @@ public: /// qualifiers from the outermost type. const ArrayType *castAsArrayTypeUnsafe() const; - /// Determine whether this type had the specified attribute applied to it - /// (looking through top-level type sugar). - bool hasAttr(attr::Kind AK) const; - /// Get the base element type of this type, potentially discarding type /// qualifiers. This should never be used when type qualifiers /// are meaningful. @@ -4207,7 +4193,56 @@ public: /// - the canonical type is VectorType(16, int) class AttributedType : public Type, public llvm::FoldingSetNode { public: - using Kind = attr::Kind; + // It is really silly to have yet another attribute-kind enum, but + // clang::attr::Kind doesn't currently cover the pure type attrs. + enum Kind { + // Expression operand. + attr_address_space, + attr_regparm, + attr_vector_size, + attr_neon_vector_type, + attr_neon_polyvector_type, + + FirstExprOperandKind = attr_address_space, + LastExprOperandKind = attr_neon_polyvector_type, + + // Enumerated operand (string or keyword). + attr_objc_gc, + attr_objc_ownership, + attr_pcs, + attr_pcs_vfp, + + FirstEnumOperandKind = attr_objc_gc, + LastEnumOperandKind = attr_pcs_vfp, + + // No operand. + attr_noreturn, + attr_nocf_check, + attr_cdecl, + attr_fastcall, + attr_stdcall, + attr_thiscall, + attr_regcall, + attr_pascal, + attr_swiftcall, + attr_vectorcall, + attr_inteloclbicc, + attr_ms_abi, + attr_sysv_abi, + attr_preserve_most, + attr_preserve_all, + attr_ptr32, + attr_ptr64, + attr_sptr, + attr_uptr, + attr_nonnull, + attr_ns_returns_retained, + attr_nullable, + attr_null_unspecified, + attr_objc_kindof, + attr_objc_inert_unsafe_unretained, + attr_lifetimebound, + }; private: friend class ASTContext; // ASTContext creates these @@ -4215,7 +4250,7 @@ private: QualType ModifiedType; QualType EquivalentType; - AttributedType(QualType canon, attr::Kind attrKind, QualType modified, + AttributedType(QualType canon, Kind attrKind, QualType modified, QualType equivalent) : Type(Attributed, canon, equivalent->isDependentType(), equivalent->isInstantiationDependentType(), @@ -4264,13 +4299,13 @@ public: static Kind getNullabilityAttrKind(NullabilityKind kind) { switch (kind) { case NullabilityKind::NonNull: - return attr::TypeNonNull; + return attr_nonnull; case NullabilityKind::Nullable: - return attr::TypeNullable; + return attr_nullable; case NullabilityKind::Unspecified: - return attr::TypeNullUnspecified; + return attr_null_unspecified; } llvm_unreachable("Unknown nullability kind."); } Modified: cfe/trunk/include/clang/AST/TypeLoc.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/TypeLoc.h (original) +++ cfe/trunk/include/clang/AST/TypeLoc.h Mon Aug 13 18:55:37 2018 @@ -15,7 +15,6 @@ #ifndef LLVM_CLANG_AST_TYPELOC_H #define LLVM_CLANG_AST_TYPELOC_H -#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" @@ -850,7 +849,16 @@ class SubstTemplateTypeParmPackTypeLoc : }; struct AttributedLocInfo { - const Attr *TypeAttr; + union { + Expr *ExprOperand; + + /// A raw SourceLocation. + unsigned EnumOperandLoc; + }; + + SourceRange OperandParens; + + SourceLocation AttrLoc; }; /// Type source information for an attributed type. @@ -859,10 +867,24 @@ class AttributedTypeLoc : public Concret AttributedType, AttributedLocInfo> { public: - attr::Kind getAttrKind() const { + AttributedType::Kind getAttrKind() const { return getTypePtr()->getAttrKind(); } + bool hasAttrExprOperand() const { + return (getAttrKind() >= AttributedType::FirstExprOperandKind && + getAttrKind() <= AttributedType::LastExprOperandKind); + } + + bool hasAttrEnumOperand() const { + return (getAttrKind() >= AttributedType::FirstEnumOperandKind && + getAttrKind() <= AttributedType::LastEnumOperandKind); + } + + bool hasAttrOperand() const { + return hasAttrExprOperand() || hasAttrEnumOperand(); + } + bool isQualifier() const { return getTypePtr()->isQualifier(); } @@ -875,16 +897,51 @@ public: return getInnerTypeLoc(); } - /// The type attribute. - const Attr *getAttr() const { - return getLocalData()->TypeAttr; - } - void setAttr(const Attr *A) { - getLocalData()->TypeAttr = A; - } - - template<typename T> const T *getAttrAs() { - return dyn_cast_or_null<T>(getAttr()); + /// The location of the attribute name, i.e. + /// __attribute__((regparm(1000))) + /// ^~~~~~~ + SourceLocation getAttrNameLoc() const { + return getLocalData()->AttrLoc; + } + void setAttrNameLoc(SourceLocation loc) { + getLocalData()->AttrLoc = loc; + } + + /// The attribute's expression operand, if it has one. + /// void *cur_thread __attribute__((address_space(21))) + /// ^~ + Expr *getAttrExprOperand() const { + assert(hasAttrExprOperand()); + return getLocalData()->ExprOperand; + } + void setAttrExprOperand(Expr *e) { + assert(hasAttrExprOperand()); + getLocalData()->ExprOperand = e; + } + + /// The location of the attribute's enumerated operand, if it has one. + /// void * __attribute__((objc_gc(weak))) + /// ^~~~ + SourceLocation getAttrEnumOperandLoc() const { + assert(hasAttrEnumOperand()); + return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc); + } + void setAttrEnumOperandLoc(SourceLocation loc) { + assert(hasAttrEnumOperand()); + getLocalData()->EnumOperandLoc = loc.getRawEncoding(); + } + + /// The location of the parentheses around the operand, if there is + /// an operand. + /// void * __attribute__((objc_gc(weak))) + /// ^ ^ + SourceRange getAttrOperandParensRange() const { + assert(hasAttrOperand()); + return getLocalData()->OperandParens; + } + void setAttrOperandParensRange(SourceRange range) { + assert(hasAttrOperand()); + getLocalData()->OperandParens = range; } SourceRange getLocalSourceRange() const { @@ -897,11 +954,21 @@ public: // ^~ ~~ // That enclosure doesn't necessarily belong to a single attribute // anyway. - return getAttr() ? getAttr()->getRange() : SourceRange(); + SourceRange range(getAttrNameLoc()); + if (hasAttrOperand()) + range.setEnd(getAttrOperandParensRange().getEnd()); + return range; } void initializeLocal(ASTContext &Context, SourceLocation loc) { - setAttr(nullptr); + setAttrNameLoc(loc); + if (hasAttrExprOperand()) { + setAttrOperandParensRange(SourceRange(loc)); + setAttrExprOperand(nullptr); + } else if (hasAttrEnumOperand()) { + setAttrOperandParensRange(SourceRange(loc)); + setAttrEnumOperandLoc(loc); + } } QualType getInnerType() const { Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Mon Aug 13 18:55:37 2018 @@ -494,7 +494,10 @@ class Attr { } /// A type attribute is not processed on a declaration or a statement. -class TypeAttr : Attr; +class TypeAttr : Attr { + // By default, type attributes do not get an AST node. + let ASTNode = 0; +} /// A stmt attribute is not processed on a declaration or a type. class StmtAttr : Attr; @@ -564,8 +567,6 @@ def AddressSpace : TypeAttr { let Spellings = [Clang<"address_space">]; let Args = [IntArgument<"AddressSpace">]; let Documentation = [Undocumented]; - // Represented as a qualifier or DependentAddressSpaceType instead. - let ASTNode = 0; } def Alias : Attr { @@ -1223,7 +1224,7 @@ def LayoutVersion : InheritableAttr, Tar let Documentation = [LayoutVersionDocs]; } -def LifetimeBound : DeclOrTypeAttr { +def LifetimeBound : InheritableAttr { let Spellings = [Clang<"lifetimebound", 0>]; let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>; let Documentation = [LifetimeBoundDocs]; @@ -1326,16 +1327,12 @@ def NeonPolyVectorType : TypeAttr { let Spellings = [Clang<"neon_polyvector_type">]; let Args = [IntArgument<"NumElements">]; let Documentation = [Undocumented]; - // Represented as VectorType instead. - let ASTNode = 0; } def NeonVectorType : TypeAttr { let Spellings = [Clang<"neon_vector_type">]; let Args = [IntArgument<"NumElements">]; let Documentation = [Undocumented]; - // Represented as VectorType instead. - let ASTNode = 0; } def ReturnsTwice : InheritableAttr { @@ -1510,14 +1507,6 @@ def TypeNullUnspecified : TypeAttr { let Documentation = [TypeNullUnspecifiedDocs]; } -// This is a marker used to indicate that an __unsafe_unretained qualifier was -// ignored because ARC is not enabled. The usual representation for this -// qualifier is as an ObjCOwnership attribute with Kind == "none". -def ObjCInertUnsafeUnretained : TypeAttr { - let Spellings = [Keyword<"__unsafe_unretained">]; - let Documentation = [Undocumented]; -} - def ObjCKindOf : TypeAttr { let Spellings = [Keyword<"__kindof">]; let Documentation = [Undocumented]; @@ -1605,7 +1594,7 @@ def ObjCBridgeRelated : InheritableAttr let Documentation = [Undocumented]; } -def NSReturnsRetained : DeclOrTypeAttr { +def NSReturnsRetained : InheritableAttr { let Spellings = [Clang<"ns_returns_retained">]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; @@ -1790,8 +1779,6 @@ def Regparm : TypeAttr { let Spellings = [GCC<"regparm">]; let Args = [UnsignedArgument<"NumParams">]; let Documentation = [RegparmDocs]; - // Represented as part of the enclosing function type. - let ASTNode = 0; } def ReqdWorkGroupSize : InheritableAttr { @@ -2080,9 +2067,10 @@ def ObjCGC : TypeAttr { let Documentation = [Undocumented]; } -def ObjCOwnership : DeclOrTypeAttr { +def ObjCOwnership : InheritableAttr { let Spellings = [Clang<"objc_ownership">]; let Args = [IdentifierArgument<"Kind">]; + let ASTNode = 0; let Documentation = [Undocumented]; } @@ -2120,8 +2108,6 @@ def VectorSize : TypeAttr { let Spellings = [GCC<"vector_size">]; let Args = [ExprArgument<"NumBytes">]; let Documentation = [Undocumented]; - // Represented as VectorType instead. - let ASTNode = 0; } def VecTypeHint : InheritableAttr { @@ -2216,7 +2202,7 @@ def AnyX86NoCallerSavedRegisters : Inher let Documentation = [AnyX86NoCallerSavedRegistersDocs]; } -def AnyX86NoCfCheck : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86>{ +def AnyX86NoCfCheck : InheritableAttr, TargetSpecificAttr<TargetAnyX86>{ let Spellings = [GCC<"nocf_check">]; let Subjects = SubjectList<[FunctionLike]>; let Documentation = [AnyX86NoCfCheckDocs]; Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Mon Aug 13 18:55:37 2018 @@ -1435,6 +1435,8 @@ public: TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S); TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy); + TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, + TypeSourceInfo *ReturnTypeInfo); /// Package the given type and TSI into a ParsedType. ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo); @@ -3376,6 +3378,30 @@ public: /// Valid types should not have multiple attributes with different CCs. const AttributedType *getCallingConvAttributedType(QualType T) const; + /// Check whether a nullability type specifier can be added to the given + /// type. + /// + /// \param type The type to which the nullability specifier will be + /// added. On success, this type will be updated appropriately. + /// + /// \param nullability The nullability specifier to add. + /// + /// \param nullabilityLoc The location of the nullability specifier. + /// + /// \param isContextSensitive Whether this nullability specifier was + /// written as a context-sensitive keyword (in an Objective-C + /// method) or an Objective-C property attribute, rather than as an + /// underscored type specifier. + /// + /// \param allowArrayTypes Whether to accept nullability specifiers on an + /// array type (e.g., because it will decay to a pointer). + /// + /// \returns true if nullability cannot be applied, false otherwise. + bool checkNullabilityTypeSpecifier(QualType &type, NullabilityKind nullability, + SourceLocation nullabilityLoc, + bool isContextSensitive, + bool allowArrayTypes); + /// Stmt attributes - this routine is the top level dispatcher. StmtResult ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributesView &Attrs, @@ -8045,6 +8071,10 @@ public: SourceLocation ProtocolRAngleLoc, bool FailOnError = false); + /// Check the application of the Objective-C '__kindof' qualifier to + /// the given type. + bool checkObjCKindOfType(QualType &type, SourceLocation loc); + /// Ensure attributes are consistent with type. /// \param [in, out] Attributes The attributes to check; they will /// be modified to be consistent with \p PropertyTy. Modified: cfe/trunk/include/clang/Serialization/ASTReader.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTReader.h (original) +++ cfe/trunk/include/clang/Serialization/ASTReader.h Mon Aug 13 18:55:37 2018 @@ -2245,9 +2245,6 @@ public: CXXTemporary *ReadCXXTemporary(ModuleFile &F, const RecordData &Record, unsigned &Idx); - /// Reads one attribute from the current stream position. - Attr *ReadAttr(ModuleFile &M, const RecordData &Record, unsigned &Idx); - /// Reads attributes from the current stream position. void ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs); @@ -2633,11 +2630,6 @@ public: return ASTReader::ReadVersionTuple(Record, Idx); } - /// Reads one attribute from the current stream position, advancing Idx. - Attr *readAttr() { - return Reader->ReadAttr(*F, Record, Idx); - } - /// Reads attributes from the current stream position, advancing Idx. void readAttributes(AttrVec &Attrs) { return Reader->ReadAttributes(*this, Attrs); Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTWriter.h (original) +++ cfe/trunk/include/clang/Serialization/ASTWriter.h Mon Aug 13 18:55:37 2018 @@ -955,9 +955,6 @@ public: return Writer->AddVersionTuple(Version, *Record); } - // Emit an attribute. - void AddAttr(const Attr *A); - /// Emit a list of attributes. void AddAttributes(ArrayRef<const Attr*> Attrs); }; Modified: cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp (original) +++ cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp Mon Aug 13 18:55:37 2018 @@ -81,11 +81,10 @@ public: } bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) { - auto *OwnershipAttr = TL.getAttrAs<ObjCOwnershipAttr>(); - if (!OwnershipAttr) + if (TL.getAttrKind() != AttributedType::attr_objc_ownership) return false; - SourceLocation Loc = OwnershipAttr->getLocation(); + SourceLocation Loc = TL.getAttrNameLoc(); unsigned RawLoc = Loc.getRawEncoding(); if (MigrateCtx.AttrSet.count(RawLoc)) return true; @@ -94,7 +93,13 @@ public: SourceManager &SM = Ctx.getSourceManager(); if (Loc.isMacroID()) Loc = SM.getImmediateExpansionRange(Loc).getBegin(); - StringRef Spell = OwnershipAttr->getKind()->getName(); + SmallString<32> Buf; + bool Invalid = false; + StringRef Spell = Lexer::getSpelling( + SM.getSpellingLoc(TL.getAttrEnumOperandLoc()), + Buf, SM, Ctx.getLangOpts(), &Invalid); + if (Invalid) + return false; MigrationContext::GCAttrOccurrence::AttrKind Kind; if (Spell == "strong") Kind = MigrationContext::GCAttrOccurrence::Strong; @@ -279,7 +284,7 @@ static void checkAllAtProps(MigrationCon } for (unsigned i = 0, e = ATLs.size(); i != e; ++i) { - SourceLocation Loc = ATLs[i].first.getAttr()->getLocation(); + SourceLocation Loc = ATLs[i].first.getAttrNameLoc(); if (Loc.isMacroID()) Loc = MigrateCtx.Pass.Ctx.getSourceManager() .getImmediateExpansionRange(Loc) Modified: cfe/trunk/lib/ARCMigrate/Transforms.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/ARCMigrate/Transforms.cpp (original) +++ cfe/trunk/lib/ARCMigrate/Transforms.cpp Mon Aug 13 18:55:37 2018 @@ -359,7 +359,7 @@ MigrationContext::~MigrationContext() { bool MigrationContext::isGCOwnedNonObjC(QualType T) { while (!T.isNull()) { if (const AttributedType *AttrT = T->getAs<AttributedType>()) { - if (AttrT->getAttrKind() == attr::ObjCOwnership) + if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership) return !AttrT->getModifiedType()->isObjCRetainableType(); } Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Mon Aug 13 18:55:37 2018 @@ -3876,7 +3876,7 @@ QualType ASTContext::getEnumType(const E return QualType(newType, 0); } -QualType ASTContext::getAttributedType(attr::Kind attrKind, +QualType ASTContext::getAttributedType(AttributedType::Kind attrKind, QualType modifiedType, QualType equivalentType) { llvm::FoldingSetNodeID id; Modified: cfe/trunk/lib/AST/Type.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/AST/Type.cpp (original) +++ cfe/trunk/lib/AST/Type.cpp Mon Aug 13 18:55:37 2018 @@ -592,6 +592,28 @@ bool Type::isObjCClassOrClassKindOfType( return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType(); } +/// Was this type written with the special inert-in-MRC __unsafe_unretained +/// qualifier? +/// +/// This approximates the answer to the following question: if this +/// translation unit were compiled in ARC, would this type be qualified +/// with __unsafe_unretained? +bool Type::isObjCInertUnsafeUnretainedType() const { + const Type *cur = this; + while (true) { + if (const auto attributed = dyn_cast<AttributedType>(cur)) { + if (attributed->getAttrKind() == + AttributedType::attr_objc_inert_unsafe_unretained) + return true; + } + + // Single-step desugar until we run out of sugar. + QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType(); + if (next.getTypePtr() == cur) return false; + cur = next.getTypePtr(); + } +} + ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, QualType can, ArrayRef<ObjCProtocolDecl *> protocols) @@ -1619,16 +1641,6 @@ TagDecl *Type::getAsTagDecl() const { return nullptr; } -bool Type::hasAttr(attr::Kind AK) const { - const Type *Cur = this; - while (const auto *AT = Cur->getAs<AttributedType>()) { - if (AT->getAttrKind() == AK) - return true; - Cur = AT->getEquivalentType().getTypePtr(); - } - return false; -} - namespace { class GetContainedDeducedTypeVisitor : @@ -3155,58 +3167,105 @@ bool RecordType::hasConstFields() const } bool AttributedType::isQualifier() const { - // FIXME: Generate this with TableGen. switch (getAttrKind()) { // These are type qualifiers in the traditional C sense: they annotate // something about a specific value/variable of a type. (They aren't // always part of the canonical type, though.) - case attr::ObjCGC: - case attr::ObjCOwnership: - case attr::ObjCInertUnsafeUnretained: - case attr::TypeNonNull: - case attr::TypeNullable: - case attr::TypeNullUnspecified: - case attr::LifetimeBound: - return true; - - // All other type attributes aren't qualifiers; they rewrite the modified - // type to be a semantically different type. - default: + case AttributedType::attr_address_space: + case AttributedType::attr_objc_gc: + case AttributedType::attr_objc_ownership: + case AttributedType::attr_objc_inert_unsafe_unretained: + case AttributedType::attr_nonnull: + case AttributedType::attr_nullable: + case AttributedType::attr_null_unspecified: + case AttributedType::attr_lifetimebound: + return true; + + // These aren't qualifiers; they rewrite the modified type to be a + // semantically different type. + case AttributedType::attr_regparm: + case AttributedType::attr_vector_size: + case AttributedType::attr_neon_vector_type: + case AttributedType::attr_neon_polyvector_type: + case AttributedType::attr_pcs: + case AttributedType::attr_pcs_vfp: + case AttributedType::attr_noreturn: + case AttributedType::attr_cdecl: + case AttributedType::attr_fastcall: + case AttributedType::attr_stdcall: + case AttributedType::attr_thiscall: + case AttributedType::attr_regcall: + 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: + case AttributedType::attr_ptr64: + case AttributedType::attr_sptr: + case AttributedType::attr_uptr: + case AttributedType::attr_objc_kindof: + case AttributedType::attr_ns_returns_retained: + case AttributedType::attr_nocf_check: return false; } + llvm_unreachable("bad attributed type kind"); } bool AttributedType::isMSTypeSpec() const { - // FIXME: Generate this with TableGen? switch (getAttrKind()) { - default: return false; - case attr::Ptr32: - case attr::Ptr64: - case attr::SPtr: - case attr::UPtr: + default: return false; + case attr_ptr32: + case attr_ptr64: + case attr_sptr: + case attr_uptr: return true; } llvm_unreachable("invalid attr kind"); } bool AttributedType::isCallingConv() const { - // FIXME: Generate this with TableGen. switch (getAttrKind()) { - default: return false; - case attr::Pcs: - case attr::CDecl: - case attr::FastCall: - case attr::StdCall: - case attr::ThisCall: - case attr::RegCall: - case attr::SwiftCall: - case attr::VectorCall: - case attr::Pascal: - case attr::MSABI: - case attr::SysVABI: - case attr::IntelOclBicc: - case attr::PreserveMost: - case attr::PreserveAll: + case attr_ptr32: + case attr_ptr64: + case attr_sptr: + case attr_uptr: + case attr_address_space: + case attr_regparm: + case attr_vector_size: + case attr_neon_vector_type: + case attr_neon_polyvector_type: + case attr_objc_gc: + case attr_objc_ownership: + case attr_objc_inert_unsafe_unretained: + case attr_noreturn: + case attr_nonnull: + case attr_ns_returns_retained: + case attr_nullable: + case attr_null_unspecified: + case attr_objc_kindof: + case attr_nocf_check: + case attr_lifetimebound: + return false; + + case attr_pcs: + case attr_pcs_vfp: + case attr_cdecl: + case attr_fastcall: + case attr_stdcall: + case attr_thiscall: + case attr_regcall: + 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"); @@ -3649,18 +3708,23 @@ LinkageInfo Type::getLinkageAndVisibilit return LinkageComputer{}.getTypeLinkageAndVisibility(this); } -Optional<NullabilityKind> -Type::getNullability(const ASTContext &Context) const { - QualType Type(this, 0); - while (const auto *AT = Type->getAs<AttributedType>()) { +Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const { + QualType type(this, 0); + do { // Check whether this is an attributed type with nullability // information. - if (auto Nullability = AT->getImmediateNullability()) - return Nullability; + if (auto attributed = dyn_cast<AttributedType>(type.getTypePtr())) { + if (auto nullability = attributed->getImmediateNullability()) + return nullability; + } - Type = AT->getEquivalentType(); - } - return None; + // Desugar the type. If desugaring does nothing, we're done. + QualType desugared = type.getSingleStepDesugaredType(context); + if (desugared.getTypePtr() == type.getTypePtr()) + return None; + + type = desugared; + } while (true); } bool Type::canHaveNullability(bool ResultIfUnknown) const { @@ -3773,13 +3837,12 @@ bool Type::canHaveNullability(bool Resul llvm_unreachable("bad type kind!"); } -llvm::Optional<NullabilityKind> -AttributedType::getImmediateNullability() const { - if (getAttrKind() == attr::TypeNonNull) +llvm::Optional<NullabilityKind> AttributedType::getImmediateNullability() const { + if (getAttrKind() == AttributedType::attr_nonnull) return NullabilityKind::NonNull; - if (getAttrKind() == attr::TypeNullable) + if (getAttrKind() == AttributedType::attr_nullable) return NullabilityKind::Nullable; - if (getAttrKind() == attr::TypeNullUnspecified) + if (getAttrKind() == AttributedType::attr_null_unspecified) return NullabilityKind::Unspecified; return None; } Modified: cfe/trunk/lib/AST/TypeLoc.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/AST/TypeLoc.cpp (original) +++ cfe/trunk/lib/AST/TypeLoc.cpp Mon Aug 13 18:55:37 2018 @@ -404,11 +404,11 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLo } SourceLocation TypeLoc::findNullabilityLoc() const { - if (auto ATL = getAs<AttributedTypeLoc>()) { - const Attr *A = ATL.getAttr(); - if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) || - isa<TypeNullUnspecifiedAttr>(A))) - return A->getLocation(); + if (auto attributedLoc = getAs<AttributedTypeLoc>()) { + if (attributedLoc.getAttrKind() == AttributedType::attr_nullable || + attributedLoc.getAttrKind() == AttributedType::attr_nonnull || + attributedLoc.getAttrKind() == AttributedType::attr_null_unspecified) + return attributedLoc.getAttrNameLoc(); } return {}; Modified: cfe/trunk/lib/AST/TypePrinter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/AST/TypePrinter.cpp (original) +++ cfe/trunk/lib/AST/TypePrinter.cpp Mon Aug 13 18:55:37 2018 @@ -1354,14 +1354,12 @@ void TypePrinter::printPackExpansionAfte void TypePrinter::printAttributedBefore(const AttributedType *T, raw_ostream &OS) { - // FIXME: Generate this with TableGen. - // Prefer the macro forms of the GC and ownership qualifiers. - if (T->getAttrKind() == attr::ObjCGC || - T->getAttrKind() == attr::ObjCOwnership) + if (T->getAttrKind() == AttributedType::attr_objc_gc || + T->getAttrKind() == AttributedType::attr_objc_ownership) return printBefore(T->getEquivalentType(), OS); - if (T->getAttrKind() == attr::ObjCKindOf) + if (T->getAttrKind() == AttributedType::attr_objc_kindof) OS << "__kindof "; printBefore(T->getModifiedType(), OS); @@ -1369,21 +1367,23 @@ void TypePrinter::printAttributedBefore( if (T->isMSTypeSpec()) { switch (T->getAttrKind()) { default: return; - case attr::Ptr32: OS << " __ptr32"; break; - case attr::Ptr64: OS << " __ptr64"; break; - case attr::SPtr: OS << " __sptr"; break; - case attr::UPtr: OS << " __uptr"; break; + case AttributedType::attr_ptr32: OS << " __ptr32"; break; + case AttributedType::attr_ptr64: OS << " __ptr64"; break; + case AttributedType::attr_sptr: OS << " __sptr"; break; + case AttributedType::attr_uptr: OS << " __uptr"; break; } spaceBeforePlaceHolder(OS); } // Print nullability type specifiers. - if (T->getImmediateNullability()) { - if (T->getAttrKind() == attr::TypeNonNull) + if (T->getAttrKind() == AttributedType::attr_nonnull || + T->getAttrKind() == AttributedType::attr_nullable || + T->getAttrKind() == AttributedType::attr_null_unspecified) { + if (T->getAttrKind() == AttributedType::attr_nonnull) OS << " _Nonnull"; - else if (T->getAttrKind() == attr::TypeNullable) + else if (T->getAttrKind() == AttributedType::attr_nullable) OS << " _Nullable"; - else if (T->getAttrKind() == attr::TypeNullUnspecified) + else if (T->getAttrKind() == AttributedType::attr_null_unspecified) OS << " _Null_unspecified"; else llvm_unreachable("unhandled nullability"); @@ -1393,11 +1393,9 @@ void TypePrinter::printAttributedBefore( void TypePrinter::printAttributedAfter(const AttributedType *T, raw_ostream &OS) { - // FIXME: Generate this with TableGen. - // Prefer the macro forms of the GC and ownership qualifiers. - if (T->getAttrKind() == attr::ObjCGC || - T->getAttrKind() == attr::ObjCOwnership) + if (T->getAttrKind() == AttributedType::attr_objc_gc || + T->getAttrKind() == AttributedType::attr_objc_ownership) return printAfter(T->getEquivalentType(), OS); // If this is a calling convention attribute, don't print the implicit CC from @@ -1408,74 +1406,107 @@ void TypePrinter::printAttributedAfter(c // Some attributes are printed as qualifiers before the type, so we have // nothing left to do. - if (T->getAttrKind() == attr::ObjCKindOf || - T->isMSTypeSpec() || T->getImmediateNullability()) + if (T->getAttrKind() == AttributedType::attr_objc_kindof || + T->isMSTypeSpec() || + T->getAttrKind() == AttributedType::attr_nonnull || + T->getAttrKind() == AttributedType::attr_nullable || + T->getAttrKind() == AttributedType::attr_null_unspecified) return; // Don't print the inert __unsafe_unretained attribute at all. - if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained) + if (T->getAttrKind() == AttributedType::attr_objc_inert_unsafe_unretained) return; // Don't print ns_returns_retained unless it had an effect. - if (T->getAttrKind() == attr::NSReturnsRetained && + if (T->getAttrKind() == AttributedType::attr_ns_returns_retained && !T->getEquivalentType()->castAs<FunctionType>() ->getExtInfo().getProducesResult()) return; - if (T->getAttrKind() == attr::LifetimeBound) { + if (T->getAttrKind() == AttributedType::attr_lifetimebound) { OS << " [[clang::lifetimebound]]"; return; } OS << " __attribute__(("; switch (T->getAttrKind()) { -#define TYPE_ATTR(NAME) -#define DECL_OR_TYPE_ATTR(NAME) -#define ATTR(NAME) case attr::NAME: -#include "clang/Basic/AttrList.inc" - llvm_unreachable("non-type attribute attached to type"); - - case attr::OpenCLPrivateAddressSpace: - case attr::OpenCLGlobalAddressSpace: - case attr::OpenCLLocalAddressSpace: - case attr::OpenCLConstantAddressSpace: - case attr::OpenCLGenericAddressSpace: - // FIXME: Update printAttributedBefore to print these once we generate - // AttributedType nodes for them. - break; - - case attr::LifetimeBound: - case attr::TypeNonNull: - case attr::TypeNullable: - case attr::TypeNullUnspecified: - case attr::ObjCGC: - case attr::ObjCInertUnsafeUnretained: - case attr::ObjCKindOf: - case attr::ObjCOwnership: - case attr::Ptr32: - case attr::Ptr64: - case attr::SPtr: - case attr::UPtr: + case AttributedType::attr_lifetimebound: + case AttributedType::attr_nonnull: + case AttributedType::attr_nullable: + case AttributedType::attr_null_unspecified: + case AttributedType::attr_objc_gc: + case AttributedType::attr_objc_inert_unsafe_unretained: + case AttributedType::attr_objc_kindof: + case AttributedType::attr_objc_ownership: + case AttributedType::attr_ptr32: + case AttributedType::attr_ptr64: + case AttributedType::attr_sptr: + case AttributedType::attr_uptr: llvm_unreachable("This attribute should have been handled already"); - case attr::NSReturnsRetained: + case AttributedType::attr_address_space: + OS << "address_space("; + // FIXME: printing the raw LangAS value is wrong. This should probably + // use the same code as Qualifiers::print() + OS << (unsigned)T->getEquivalentType().getAddressSpace(); + OS << ')'; + break; + + case AttributedType::attr_vector_size: + OS << "__vector_size__("; + if (const auto *vector = T->getEquivalentType()->getAs<VectorType>()) { + OS << vector->getNumElements(); + OS << " * sizeof("; + print(vector->getElementType(), OS, StringRef()); + OS << ')'; + } + OS << ')'; + break; + + case AttributedType::attr_neon_vector_type: + case AttributedType::attr_neon_polyvector_type: { + if (T->getAttrKind() == AttributedType::attr_neon_vector_type) + OS << "neon_vector_type("; + else + OS << "neon_polyvector_type("; + const auto *vector = T->getEquivalentType()->getAs<VectorType>(); + OS << vector->getNumElements(); + OS << ')'; + break; + } + + case AttributedType::attr_regparm: { + // FIXME: When Sema learns to form this AttributedType, avoid printing the + // attribute again in printFunctionProtoAfter. + OS << "regparm("; + QualType t = T->getEquivalentType(); + while (!t->isFunctionType()) + t = t->getPointeeType(); + OS << t->getAs<FunctionType>()->getRegParmType(); + OS << ')'; + break; + } + + case AttributedType::attr_ns_returns_retained: OS << "ns_returns_retained"; break; // FIXME: When Sema learns to form this AttributedType, avoid printing the // attribute again in printFunctionProtoAfter. - case attr::AnyX86NoCfCheck: OS << "nocf_check"; break; - case attr::CDecl: OS << "cdecl"; break; - case attr::FastCall: OS << "fastcall"; break; - case attr::StdCall: OS << "stdcall"; break; - case attr::ThisCall: OS << "thiscall"; break; - case attr::SwiftCall: OS << "swiftcall"; break; - case attr::VectorCall: OS << "vectorcall"; break; - case attr::Pascal: OS << "pascal"; break; - case attr::MSABI: OS << "ms_abi"; break; - case attr::SysVABI: OS << "sysv_abi"; break; - case attr::RegCall: OS << "regcall"; break; - case attr::Pcs: { + case AttributedType::attr_noreturn: OS << "noreturn"; break; + case AttributedType::attr_nocf_check: OS << "nocf_check"; break; + case AttributedType::attr_cdecl: OS << "cdecl"; break; + 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; + case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break; + case AttributedType::attr_regcall: OS << "regcall"; break; + case AttributedType::attr_pcs: + case AttributedType::attr_pcs_vfp: { OS << "pcs("; QualType t = T->getEquivalentType(); while (!t->isFunctionType()) @@ -1486,12 +1517,12 @@ void TypePrinter::printAttributedAfter(c break; } - case attr::IntelOclBicc: OS << "inteloclbicc"; break; - case attr::PreserveMost: + case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break; + case AttributedType::attr_preserve_most: OS << "preserve_most"; break; - case attr::PreserveAll: + case AttributedType::attr_preserve_all: OS << "preserve_all"; break; } Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug 13 18:55:37 2018 @@ -5999,14 +5999,14 @@ static void checkAttributesAfterMerging( // The [[lifetimebound]] attribute can be applied to the implicit object // parameter of a non-static member function (other than a ctor or dtor) // by applying it to the function type. - if (const auto *A = ATL.getAttrAs<LifetimeBoundAttr>()) { + if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) { const auto *MD = dyn_cast<CXXMethodDecl>(FD); if (!MD || MD->isStatic()) { - S.Diag(A->getLocation(), diag::err_lifetimebound_no_object_param) - << !MD << A->getRange(); + S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_no_object_param) + << !MD << ATL.getLocalSourceRange(); } else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) { - S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor) - << isa<CXXDestructorDecl>(MD) << A->getRange(); + S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_ctor_dtor) + << isa<CXXDestructorDecl>(MD) << ATL.getLocalSourceRange(); } } } Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Aug 13 18:55:37 2018 @@ -14658,15 +14658,15 @@ static bool captureInBlock(BlockScopeInf // Warn about implicitly autoreleasing indirect parameters captured by blocks. if (const auto *PT = CaptureType->getAs<PointerType>()) { // This function finds out whether there is an AttributedType of kind - // attr::ObjCOwnership in Ty. The existence of AttributedType of kind - // attr::ObjCOwnership implies __autoreleasing was explicitly specified + // attr_objc_ownership in Ty. The existence of AttributedType of kind + // attr_objc_ownership implies __autoreleasing was explicitly specified // rather than being added implicitly by the compiler. auto IsObjCOwnershipAttributedType = [](QualType Ty) { while (const auto *AttrTy = Ty->getAs<AttributedType>()) { - if (AttrTy->getAttrKind() == attr::ObjCOwnership) + if (AttrTy->getAttrKind() == AttributedType::attr_objc_ownership) return true; - // Peel off AttributedTypes that are not of kind ObjCOwnership. + // Peel off AttributedTypes that are not of kind objc_ownership. Ty = AttrTy->getModifiedType(); } Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Aug 13 18:55:37 2018 @@ -6360,7 +6360,7 @@ static bool implicitObjectParamIsLifetim for (TypeLoc TL = TSI->getTypeLoc(); (ATL = TL.getAsAdjusted<AttributedTypeLoc>()); TL = ATL.getModifiedLoc()) { - if (ATL.getAttrAs<LifetimeBoundAttr>()) + if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) return true; } return false; Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original) +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Aug 13 18:55:37 2018 @@ -2384,7 +2384,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope QualType modifiedTy = resultTy; if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) { if (*nullability == NullabilityKind::Unspecified) - resultTy = Context.getAttributedType(attr::TypeNonNull, + resultTy = Context.getAttributedType(AttributedType::attr_nonnull, modifiedTy, modifiedTy); } } @@ -2458,7 +2458,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope QualType modifiedTy = paramTy; if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){ if (*nullability == NullabilityKind::Unspecified) - paramTy = Context.getAttributedType(attr::TypeNullable, + paramTy = Context.getAttributedType(AttributedType::attr_nullable, modifiedTy, modifiedTy); } } Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Mon Aug 13 18:55:37 2018 @@ -172,16 +172,6 @@ namespace { /// processing is complete. SmallVector<ParsedAttr *, 2> ignoredTypeAttrs; - /// Attributes corresponding to AttributedTypeLocs that we have not yet - /// populated. - // FIXME: The two-phase mechanism by which we construct Types and fill - // their TypeLocs makes it hard to correctly assign these. We keep the - // attributes in creation order as an attempt to make them line up - // properly. - using TypeAttrPair = std::pair<const AttributedType*, const Attr*>; - SmallVector<TypeAttrPair, 8> AttrsForTypes; - bool AttrsForTypesSorted = true; - public: TypeProcessingState(Sema &sema, Declarator &declarator) : sema(sema), declarator(declarator), @@ -240,43 +230,6 @@ namespace { diagnoseBadTypeAttribute(getSema(), *Attr, type); } - /// Get an attributed type for the given attribute, and remember the Attr - /// object so that we can attach it to the AttributedTypeLoc. - QualType getAttributedType(Attr *A, QualType ModifiedType, - QualType EquivType) { - QualType T = - sema.Context.getAttributedType(A->getKind(), ModifiedType, EquivType); - AttrsForTypes.push_back({cast<AttributedType>(T.getTypePtr()), A}); - AttrsForTypesSorted = false; - return T; - } - - /// Extract and remove the Attr* for a given attributed type. - const Attr *takeAttrForAttributedType(const AttributedType *AT) { - if (!AttrsForTypesSorted) { - std::stable_sort(AttrsForTypes.begin(), AttrsForTypes.end(), - [](const TypeAttrPair &A, const TypeAttrPair &B) { - return A.first < B.first; - }); - AttrsForTypesSorted = true; - } - - // FIXME: This is quadratic if we have lots of reuses of the same - // attributed type. - for (auto It = std::partition_point( - AttrsForTypes.begin(), AttrsForTypes.end(), - [=](const TypeAttrPair &A) { return A.first < AT; }); - It != AttrsForTypes.end() && It->first == AT; ++It) { - if (It->second) { - const Attr *Result = It->second; - It->second = nullptr; - return Result; - } - } - - llvm_unreachable("no Attr* for AttributedType*"); - } - ~TypeProcessingState() { if (trivial) return; @@ -3879,32 +3832,6 @@ static bool hasOuterPointerLikeChunk(con return false; } -template<typename AttrT> -static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &Attr) { - Attr.setUsedAsTypeAttr(); - return ::new (Ctx) - AttrT(Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex()); -} - -static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr, - NullabilityKind NK) { - switch (NK) { - case NullabilityKind::NonNull: - return createSimpleAttr<TypeNonNullAttr>(Ctx, Attr); - - case NullabilityKind::Nullable: - return createSimpleAttr<TypeNullableAttr>(Ctx, Attr); - - case NullabilityKind::Unspecified: - return createSimpleAttr<TypeNullUnspecifiedAttr>(Ctx, Attr); - } - llvm_unreachable("unknown NullabilityKind"); -} - -static TypeSourceInfo * -GetTypeSourceInfoForDeclarator(TypeProcessingState &State, - QualType T, TypeSourceInfo *ReturnTypeInfo); - static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, QualType declSpecType, TypeSourceInfo *TInfo) { @@ -4257,8 +4184,9 @@ static TypeSourceInfo *GetFullTypeForDec pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), D.getDeclSpec().getEndLoc(), D.getMutableDeclSpec().getAttributes())) { - T = state.getAttributedType( - createNullabilityAttr(Context, *attr, *inferNullability), T, T); + T = Context.getAttributedType( + AttributedType::getNullabilityAttrKind(*inferNullability),T,T); + attr->setUsedAsTypeAttr(); } } } @@ -5097,7 +5025,7 @@ static TypeSourceInfo *GetFullTypeForDec if (D.isInvalidType()) return Context.getTrivialTypeSourceInfo(T); - return GetTypeSourceInfoForDeclarator(state, T, TInfo); + return S.GetTypeSourceInfoForDeclarator(D, T, TInfo); } /// GetTypeForDeclarator - Convert the type for the specified @@ -5233,25 +5161,131 @@ TypeSourceInfo *Sema::GetTypeForDeclarat return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo); } +/// Map an AttributedType::Kind to an ParsedAttr::Kind. +static ParsedAttr::Kind getAttrListKind(AttributedType::Kind kind) { + switch (kind) { + case AttributedType::attr_address_space: + return ParsedAttr::AT_AddressSpace; + case AttributedType::attr_regparm: + return ParsedAttr::AT_Regparm; + case AttributedType::attr_vector_size: + return ParsedAttr::AT_VectorSize; + case AttributedType::attr_neon_vector_type: + return ParsedAttr::AT_NeonVectorType; + case AttributedType::attr_neon_polyvector_type: + return ParsedAttr::AT_NeonPolyVectorType; + case AttributedType::attr_objc_gc: + return ParsedAttr::AT_ObjCGC; + case AttributedType::attr_objc_ownership: + case AttributedType::attr_objc_inert_unsafe_unretained: + return ParsedAttr::AT_ObjCOwnership; + case AttributedType::attr_noreturn: + return ParsedAttr::AT_NoReturn; + case AttributedType::attr_nocf_check: + return ParsedAttr::AT_AnyX86NoCfCheck; + case AttributedType::attr_cdecl: + return ParsedAttr::AT_CDecl; + case AttributedType::attr_fastcall: + return ParsedAttr::AT_FastCall; + case AttributedType::attr_stdcall: + return ParsedAttr::AT_StdCall; + case AttributedType::attr_thiscall: + return ParsedAttr::AT_ThisCall; + case AttributedType::attr_regcall: + return ParsedAttr::AT_RegCall; + case AttributedType::attr_pascal: + return ParsedAttr::AT_Pascal; + case AttributedType::attr_swiftcall: + return ParsedAttr::AT_SwiftCall; + case AttributedType::attr_vectorcall: + return ParsedAttr::AT_VectorCall; + case AttributedType::attr_pcs: + case AttributedType::attr_pcs_vfp: + return ParsedAttr::AT_Pcs; + case AttributedType::attr_inteloclbicc: + return ParsedAttr::AT_IntelOclBicc; + case AttributedType::attr_ms_abi: + return ParsedAttr::AT_MSABI; + case AttributedType::attr_sysv_abi: + return ParsedAttr::AT_SysVABI; + case AttributedType::attr_preserve_most: + return ParsedAttr::AT_PreserveMost; + case AttributedType::attr_preserve_all: + return ParsedAttr::AT_PreserveAll; + case AttributedType::attr_ptr32: + return ParsedAttr::AT_Ptr32; + case AttributedType::attr_ptr64: + return ParsedAttr::AT_Ptr64; + case AttributedType::attr_sptr: + return ParsedAttr::AT_SPtr; + case AttributedType::attr_uptr: + return ParsedAttr::AT_UPtr; + case AttributedType::attr_nonnull: + return ParsedAttr::AT_TypeNonNull; + case AttributedType::attr_nullable: + return ParsedAttr::AT_TypeNullable; + case AttributedType::attr_null_unspecified: + return ParsedAttr::AT_TypeNullUnspecified; + case AttributedType::attr_objc_kindof: + return ParsedAttr::AT_ObjCKindOf; + case AttributedType::attr_ns_returns_retained: + return ParsedAttr::AT_NSReturnsRetained; + case AttributedType::attr_lifetimebound: + return ParsedAttr::AT_LifetimeBound; + } + llvm_unreachable("unexpected attribute kind!"); +} + +static void setAttributedTypeLoc(AttributedTypeLoc TL, const ParsedAttr &attr) { + TL.setAttrNameLoc(attr.getLoc()); + if (TL.hasAttrExprOperand()) { + assert(attr.isArgExpr(0) && "mismatched attribute operand kind"); + TL.setAttrExprOperand(attr.getArgAsExpr(0)); + } else if (TL.hasAttrEnumOperand()) { + assert((attr.isArgIdent(0) || attr.isArgExpr(0)) && + "unexpected attribute operand kind"); + if (attr.isArgIdent(0)) + TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc); + else + TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc()); + } + + // FIXME: preserve this information to here. + if (TL.hasAttrOperand()) + TL.setAttrOperandParensRange(SourceRange()); +} + static void fillAttributedTypeLoc(AttributedTypeLoc TL, - TypeProcessingState &State) { - TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr())); + const ParsedAttributesView &Attrs, + const ParsedAttributesView &DeclAttrs) { + // DeclAttrs and Attrs cannot be both empty. + assert((!Attrs.empty() || !DeclAttrs.empty()) && + "no type attributes in the expected location!"); + + ParsedAttr::Kind parsedKind = getAttrListKind(TL.getAttrKind()); + // Try to search for an attribute of matching kind in Attrs list. + for (const ParsedAttr &AL : Attrs) + if (AL.getKind() == parsedKind) + return setAttributedTypeLoc(TL, AL); + + for (const ParsedAttr &AL : DeclAttrs) + if (AL.isCXX11Attribute() || AL.getKind() == parsedKind) + return setAttributedTypeLoc(TL, AL); + llvm_unreachable("no matching type attribute in expected location!"); } namespace { class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> { ASTContext &Context; - TypeProcessingState &State; const DeclSpec &DS; public: - TypeSpecLocFiller(ASTContext &Context, TypeProcessingState &State, - const DeclSpec &DS) - : Context(Context), State(State), DS(DS) {} + TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS) + : Context(Context), DS(DS) {} void VisitAttributedTypeLoc(AttributedTypeLoc TL) { + fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{}); Visit(TL.getModifiedLoc()); - fillAttributedTypeLoc(TL, State); } void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { Visit(TL.getUnqualifiedLoc()); @@ -5408,13 +5442,11 @@ namespace { class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> { ASTContext &Context; - TypeProcessingState &State; const DeclaratorChunk &Chunk; public: - DeclaratorLocFiller(ASTContext &Context, TypeProcessingState &State, - const DeclaratorChunk &Chunk) - : Context(Context), State(State), Chunk(Chunk) {} + DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk) + : Context(Context), Chunk(Chunk) {} void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { llvm_unreachable("qualified type locs not expected here!"); @@ -5424,7 +5456,7 @@ namespace { } void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, State); + fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{}); } void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing @@ -5581,13 +5613,10 @@ fillDependentAddressSpaceTypeLoc(Depende /// up in the normal place in the declaration specifiers (such as a C++ /// conversion function), this pointer will refer to a type source information /// for that return type. -static TypeSourceInfo * -GetTypeSourceInfoForDeclarator(TypeProcessingState &State, - QualType T, TypeSourceInfo *ReturnTypeInfo) { - Sema &S = State.getSema(); - Declarator &D = State.getDeclarator(); - - TypeSourceInfo *TInfo = S.Context.CreateTypeSourceInfo(T); +TypeSourceInfo * +Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, + TypeSourceInfo *ReturnTypeInfo) { + TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T); UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc(); // Handle parameter packs whose type is a pack expansion. @@ -5597,6 +5626,7 @@ GetTypeSourceInfoForDeclarator(TypeProce } for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + if (DependentAddressSpaceTypeLoc DASTL = CurrTL.getAs<DependentAddressSpaceTypeLoc>()) { fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs()); @@ -5611,7 +5641,8 @@ GetTypeSourceInfoForDeclarator(TypeProce } while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) { - fillAttributedTypeLoc(TL, State); + fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), + D.getAttributes()); CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -5619,7 +5650,7 @@ GetTypeSourceInfoForDeclarator(TypeProce while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>()) CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); - DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL); + DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL); CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -5630,7 +5661,7 @@ GetTypeSourceInfoForDeclarator(TypeProce assert(TL.getFullDataSize() == CurrTL.getFullDataSize()); memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize()); } else { - TypeSpecLocFiller(S.Context, State, D.getDeclSpec()).Visit(CurrTL); + TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL); } return TInfo; @@ -5859,7 +5890,7 @@ static bool hasDirectOwnershipQualifier( while (true) { // __strong id if (const AttributedType *attr = dyn_cast<AttributedType>(type)) { - if (attr->getAttrKind() == attr::ObjCOwnership) + if (attr->getAttrKind() == AttributedType::attr_objc_ownership) return true; type = attr->getModifiedType(); @@ -6003,9 +6034,9 @@ static bool handleObjCOwnershipTypeAttr( // the coexistence problems with __unsafe_unretained. if (!S.getLangOpts().ObjCAutoRefCount && lifetime == Qualifiers::OCL_ExplicitNone) { - type = state.getAttributedType( - createSimpleAttr<ObjCInertUnsafeUnretainedAttr>(S.Context, attr), - type, type); + type = S.Context.getAttributedType( + AttributedType::attr_objc_inert_unsafe_unretained, + type, type); return true; } @@ -6015,12 +6046,9 @@ static bool handleObjCOwnershipTypeAttr( // If we have a valid source location for the attribute, use an // AttributedType instead. - if (AttrLoc.isValid()) { - type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr( - attr.getRange(), S.Context, II, - attr.getAttributeSpellingListIndex()), - origType, type); - } + if (AttrLoc.isValid()) + type = S.Context.getAttributedType(AttributedType::attr_objc_ownership, + origType, type); auto diagnoseOrDelay = [](Sema &S, SourceLocation loc, unsigned diagnostic, QualType type) { @@ -6120,10 +6148,8 @@ static bool handleObjCGCTypeAttr(TypePro // Make an attributed type to preserve the source information. if (attr.getLoc().isValid()) - type = state.getAttributedType( - ::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II, - attr.getAttributeSpellingListIndex()), - origType, type); + type = S.Context.getAttributedType(AttributedType::attr_objc_gc, + origType, type); return true; } @@ -6266,50 +6292,37 @@ namespace { } // end anonymous namespace static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, - ParsedAttr &PAttr, QualType &Type) { + ParsedAttr &Attr, QualType &Type) { Sema &S = State.getSema(); - Attr *A; - switch (PAttr.getKind()) { - default: llvm_unreachable("Unknown attribute kind"); - case ParsedAttr::AT_Ptr32: - A = createSimpleAttr<Ptr32Attr>(S.Context, PAttr); - break; - case ParsedAttr::AT_Ptr64: - A = createSimpleAttr<Ptr64Attr>(S.Context, PAttr); - break; - case ParsedAttr::AT_SPtr: - A = createSimpleAttr<SPtrAttr>(S.Context, PAttr); - break; - case ParsedAttr::AT_UPtr: - A = createSimpleAttr<UPtrAttr>(S.Context, PAttr); - break; - } - - attr::Kind NewAttrKind = A->getKind(); + ParsedAttr::Kind Kind = Attr.getKind(); QualType Desugared = Type; const AttributedType *AT = dyn_cast<AttributedType>(Type); while (AT) { - attr::Kind CurAttrKind = AT->getAttrKind(); + AttributedType::Kind CurAttrKind = AT->getAttrKind(); // You cannot specify duplicate type attributes, so if the attribute has // already been applied, flag it. - if (NewAttrKind == CurAttrKind) { - S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) - << PAttr.getName(); + if (getAttrListKind(CurAttrKind) == Kind) { + S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact) + << Attr.getName(); return true; } // You cannot have both __sptr and __uptr on the same type, nor can you // have __ptr32 and __ptr64. - if ((CurAttrKind == attr::Ptr32 && NewAttrKind == attr::Ptr64) || - (CurAttrKind == attr::Ptr64 && NewAttrKind == attr::Ptr32)) { - S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible) + if ((CurAttrKind == AttributedType::attr_ptr32 && + Kind == ParsedAttr::AT_Ptr64) || + (CurAttrKind == AttributedType::attr_ptr64 && + Kind == ParsedAttr::AT_Ptr32)) { + S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) << "'__ptr32'" << "'__ptr64'"; return true; - } else if ((CurAttrKind == attr::SPtr && NewAttrKind == attr::UPtr) || - (CurAttrKind == attr::UPtr && NewAttrKind == attr::SPtr)) { - S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible) + } else if ((CurAttrKind == AttributedType::attr_sptr && + Kind == ParsedAttr::AT_UPtr) || + (CurAttrKind == AttributedType::attr_uptr && + Kind == ParsedAttr::AT_SPtr)) { + S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) << "'__sptr'" << "'__uptr'"; return true; } @@ -6320,64 +6333,41 @@ static bool handleMSPointerTypeQualifier // Pointer type qualifiers can only operate on pointer types, but not // pointer-to-member types. - // - // FIXME: Should we really be disallowing this attribute if there is any - // type sugar between it and the pointer (other than attributes)? Eg, this - // disallows the attribute on a parenthesized pointer. - // And if so, should we really allow *any* type attribute? if (!isa<PointerType>(Desugared)) { if (Type->isMemberPointerType()) - S.Diag(PAttr.getLoc(), diag::err_attribute_no_member_pointers) << PAttr; + S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers) << Attr; else - S.Diag(PAttr.getLoc(), diag::err_attribute_pointers_only) << PAttr << 0; + S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) << Attr << 0; return true; } - Type = State.getAttributedType(A, Type, Type); - return false; -} - -/// Map a nullability attribute kind to a nullability kind. -static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) { - switch (kind) { - case ParsedAttr::AT_TypeNonNull: - return NullabilityKind::NonNull; - - case ParsedAttr::AT_TypeNullable: - return NullabilityKind::Nullable; - - case ParsedAttr::AT_TypeNullUnspecified: - return NullabilityKind::Unspecified; - - default: - llvm_unreachable("not a nullability attribute kind"); + AttributedType::Kind TAK; + switch (Kind) { + default: llvm_unreachable("Unknown attribute kind"); + case ParsedAttr::AT_Ptr32: + TAK = AttributedType::attr_ptr32; + break; + case ParsedAttr::AT_Ptr64: + TAK = AttributedType::attr_ptr64; + break; + case ParsedAttr::AT_SPtr: + TAK = AttributedType::attr_sptr; + break; + case ParsedAttr::AT_UPtr: + TAK = AttributedType::attr_uptr; + break; } -} - -/// Applies a nullability type specifier to the given type, if possible. -/// -/// \param state The type processing state. -/// -/// \param type The type to which the nullability specifier will be -/// added. On success, this type will be updated appropriately. -/// -/// \param attr The attribute as written on the type. -/// -/// \param allowArrayTypes Whether to accept nullability specifiers on an -/// array type (e.g., because it will decay to a pointer). -/// -/// \returns true if a problem has been diagnosed, false on success. -static bool checkNullabilityTypeSpecifier(TypeProcessingState &state, - QualType &type, - ParsedAttr &attr, - bool allowOnArrayType) { - Sema &S = state.getSema(); - NullabilityKind nullability = mapNullabilityAttrKind(attr.getKind()); - SourceLocation nullabilityLoc = attr.getLoc(); - bool isContextSensitive = attr.isContextSensitiveKeywordAttribute(); + Type = S.Context.getAttributedType(TAK, Type, Type); + return false; +} - recordNullabilitySeen(S, nullabilityLoc); +bool Sema::checkNullabilityTypeSpecifier(QualType &type, + NullabilityKind nullability, + SourceLocation nullabilityLoc, + bool isContextSensitive, + bool allowOnArrayType) { + recordNullabilitySeen(*this, nullabilityLoc); // Check for existing nullability attributes on the type. QualType desugared = type; @@ -6386,7 +6376,7 @@ static bool checkNullabilityTypeSpecifie if (auto existingNullability = attributed->getImmediateNullability()) { // Duplicated nullability. if (nullability == *existingNullability) { - S.Diag(nullabilityLoc, diag::warn_nullability_duplicate) + Diag(nullabilityLoc, diag::warn_nullability_duplicate) << DiagNullabilityKind(nullability, isContextSensitive) << FixItHint::CreateRemoval(nullabilityLoc); @@ -6394,7 +6384,7 @@ static bool checkNullabilityTypeSpecifie } // Conflicting nullability. - S.Diag(nullabilityLoc, diag::err_nullability_conflicting) + Diag(nullabilityLoc, diag::err_nullability_conflicting) << DiagNullabilityKind(nullability, isContextSensitive) << DiagNullabilityKind(*existingNullability, false); return true; @@ -6407,9 +6397,9 @@ static bool checkNullabilityTypeSpecifie // This (unlike the code above) looks through typedefs that might // have nullability specifiers on them, which means we cannot // provide a useful Fix-It. - if (auto existingNullability = desugared->getNullability(S.Context)) { + if (auto existingNullability = desugared->getNullability(Context)) { if (nullability != *existingNullability) { - S.Diag(nullabilityLoc, diag::err_nullability_conflicting) + Diag(nullabilityLoc, diag::err_nullability_conflicting) << DiagNullabilityKind(nullability, isContextSensitive) << DiagNullabilityKind(*existingNullability, false); @@ -6420,7 +6410,7 @@ static bool checkNullabilityTypeSpecifie if (auto typedefNullability = AttributedType::stripOuterNullability(underlyingType)) { if (*typedefNullability == *existingNullability) { - S.Diag(typedefDecl->getLocation(), diag::note_nullability_here) + Diag(typedefDecl->getLocation(), diag::note_nullability_here) << DiagNullabilityKind(*existingNullability, false); } } @@ -6433,7 +6423,7 @@ static bool checkNullabilityTypeSpecifie // If this definitely isn't a pointer type, reject the specifier. if (!desugared->canHaveNullability() && !(allowOnArrayType && desugared->isArrayType())) { - S.Diag(nullabilityLoc, diag::err_nullability_nonpointer) + Diag(nullabilityLoc, diag::err_nullability_nonpointer) << DiagNullabilityKind(nullability, isContextSensitive) << type; return true; } @@ -6451,10 +6441,10 @@ static bool checkNullabilityTypeSpecifie if (pointeeType->isAnyPointerType() || pointeeType->isObjCObjectPointerType() || pointeeType->isMemberPointerType()) { - S.Diag(nullabilityLoc, diag::err_nullability_cs_multilevel) + Diag(nullabilityLoc, diag::err_nullability_cs_multilevel) << DiagNullabilityKind(nullability, true) << type; - S.Diag(nullabilityLoc, diag::note_nullability_type_specifier) + Diag(nullabilityLoc, diag::note_nullability_type_specifier) << DiagNullabilityKind(nullability, false) << type << FixItHint::CreateReplacement(nullabilityLoc, @@ -6464,21 +6454,16 @@ static bool checkNullabilityTypeSpecifie } // Form the attributed type. - type = state.getAttributedType( - createNullabilityAttr(S.Context, attr, nullability), type, type); + type = Context.getAttributedType( + AttributedType::getNullabilityAttrKind(nullability), type, type); return false; } -/// Check the application of the Objective-C '__kindof' qualifier to -/// the given type. -static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type, - ParsedAttr &attr) { - Sema &S = state.getSema(); - +bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) { if (isa<ObjCTypeParamType>(type)) { // Build the attributed type to record where __kindof occurred. - type = state.getAttributedType( - createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, type); + type = Context.getAttributedType(AttributedType::attr_objc_kindof, + type, type); return false; } @@ -6490,7 +6475,7 @@ static bool checkObjCKindOfType(TypeProc // If not, we can't apply __kindof. if (!objType) { // FIXME: Handle dependent types that aren't yet object types. - S.Diag(attr.getLoc(), diag::err_objc_kindof_nonobject) + Diag(loc, diag::err_objc_kindof_nonobject) << type; return true; } @@ -6498,31 +6483,45 @@ static bool checkObjCKindOfType(TypeProc // Rebuild the "equivalent" type, which pushes __kindof down into // the object type. // There is no need to apply kindof on an unqualified id type. - QualType equivType = S.Context.getObjCObjectType( + QualType equivType = Context.getObjCObjectType( objType->getBaseType(), objType->getTypeArgsAsWritten(), objType->getProtocols(), /*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true); // If we started with an object pointer type, rebuild it. if (ptrType) { - equivType = S.Context.getObjCObjectPointerType(equivType); - if (auto nullability = type->getNullability(S.Context)) { - // We create a nullability attribute from the __kindof attribute. - // Make sure that will make sense. - assert(attr.getAttributeSpellingListIndex() == 0 && - "multiple spellings for __kindof?"); - Attr *A = createNullabilityAttr(S.Context, attr, *nullability); - A->setImplicit(true); - equivType = state.getAttributedType(A, equivType, equivType); + equivType = Context.getObjCObjectPointerType(equivType); + if (auto nullability = type->getNullability(Context)) { + auto attrKind = AttributedType::getNullabilityAttrKind(*nullability); + equivType = Context.getAttributedType(attrKind, equivType, equivType); } } // Build the attributed type to record where __kindof occurred. - type = state.getAttributedType( - createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, equivType); + type = Context.getAttributedType(AttributedType::attr_objc_kindof, + type, + equivType); + return false; } +/// Map a nullability attribute kind to a nullability kind. +static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) { + switch (kind) { + case ParsedAttr::AT_TypeNonNull: + return NullabilityKind::NonNull; + + case ParsedAttr::AT_TypeNullable: + return NullabilityKind::Nullable; + + case ParsedAttr::AT_TypeNullUnspecified: + return NullabilityKind::Unspecified; + + default: + llvm_unreachable("not a nullability attribute kind"); + } +} + /// Distribute a nullability type attribute that cannot be applied to /// the type specifier to a pointer, block pointer, or member pointer /// declarator, complaining if necessary. @@ -6610,27 +6609,27 @@ static bool distributeNullabilityTypeAtt return false; } -static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) { +static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) { assert(!Attr.isInvalid()); switch (Attr.getKind()) { default: llvm_unreachable("not a calling convention attribute"); case ParsedAttr::AT_CDecl: - return createSimpleAttr<CDeclAttr>(Ctx, Attr); + return AttributedType::attr_cdecl; case ParsedAttr::AT_FastCall: - return createSimpleAttr<FastCallAttr>(Ctx, Attr); + return AttributedType::attr_fastcall; case ParsedAttr::AT_StdCall: - return createSimpleAttr<StdCallAttr>(Ctx, Attr); + return AttributedType::attr_stdcall; case ParsedAttr::AT_ThisCall: - return createSimpleAttr<ThisCallAttr>(Ctx, Attr); + return AttributedType::attr_thiscall; case ParsedAttr::AT_RegCall: - return createSimpleAttr<RegCallAttr>(Ctx, Attr); + return AttributedType::attr_regcall; case ParsedAttr::AT_Pascal: - return createSimpleAttr<PascalAttr>(Ctx, Attr); + return AttributedType::attr_pascal; case ParsedAttr::AT_SwiftCall: - return createSimpleAttr<SwiftCallAttr>(Ctx, Attr); + return AttributedType::attr_swiftcall; case ParsedAttr::AT_VectorCall: - return createSimpleAttr<VectorCallAttr>(Ctx, Attr); + return AttributedType::attr_vectorcall; case ParsedAttr::AT_Pcs: { // The attribute may have had a fixit applied where we treated an // identifier as a string literal. The contents of the string are valid, @@ -6640,22 +6639,20 @@ static Attr *getCCTypeAttr(ASTContext &C Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString(); else Str = Attr.getArgAsIdent(0)->Ident->getName(); - PcsAttr::PCSType Type; - if (!PcsAttr::ConvertStrToPCSType(Str, Type)) - llvm_unreachable("already validated the attribute"); - return ::new (Ctx) PcsAttr(Attr.getRange(), Ctx, Type, - Attr.getAttributeSpellingListIndex()); + return llvm::StringSwitch<AttributedType::Kind>(Str) + .Case("aapcs", AttributedType::attr_pcs) + .Case("aapcs-vfp", AttributedType::attr_pcs_vfp); } case ParsedAttr::AT_IntelOclBicc: - return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr); + return AttributedType::attr_inteloclbicc; case ParsedAttr::AT_MSABI: - return createSimpleAttr<MSABIAttr>(Ctx, Attr); + return AttributedType::attr_ms_abi; case ParsedAttr::AT_SysVABI: - return createSimpleAttr<SysVABIAttr>(Ctx, Attr); + return AttributedType::attr_sysv_abi; case ParsedAttr::AT_PreserveMost: - return createSimpleAttr<PreserveMostAttr>(Ctx, Attr); + return AttributedType::attr_preserve_most; case ParsedAttr::AT_PreserveAll: - return createSimpleAttr<PreserveAllAttr>(Ctx, Attr); + return AttributedType::attr_preserve_all; } llvm_unreachable("unexpected attribute kind!"); } @@ -6703,9 +6700,8 @@ static bool handleFunctionTypeAttr(TypeP = unwrapped.get()->getExtInfo().withProducesResult(true); type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); } - type = state.getAttributedType( - createSimpleAttr<NSReturnsRetainedAttr>(S.Context, attr), - origType, type); + type = S.Context.getAttributedType(AttributedType::attr_ns_returns_retained, + origType, type); return true; } @@ -6780,12 +6776,13 @@ static bool handleFunctionTypeAttr(TypeP const FunctionType *fn = unwrapped.get(); CallingConv CCOld = fn->getCallConv(); - Attr *CCAttr = getCCTypeAttr(S.Context, attr); + AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr); if (CCOld != CC) { // Error out on when there's already an attribute on the type // and the CCs don't match. - if (const AttributedType *AT = S.getCallingConvAttributedType(type)) { + const AttributedType *AT = S.getCallingConvAttributedType(type); + if (AT && AT->getAttrKind() != CCAttrKind) { S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) << FunctionType::getNameForCallConv(CC) << FunctionType::getNameForCallConv(CCOld); @@ -6839,7 +6836,7 @@ static bool handleFunctionTypeAttr(TypeP Equivalent = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); } - type = state.getAttributedType(CCAttr, type, Equivalent); + type = S.Context.getAttributedType(CCAttrKind, type, Equivalent); return true; } @@ -7195,15 +7192,14 @@ static void deduceOpenCLImplicitAddrSpac T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr); } -static void HandleLifetimeBoundAttr(TypeProcessingState &State, - QualType &CurType, - ParsedAttr &Attr) { - if (State.getDeclarator().isDeclarationOfFunction()) { - CurType = State.getAttributedType( - createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr), - CurType, CurType); +static void HandleLifetimeBoundAttr(QualType &CurType, + const ParsedAttr &Attr, + Sema &S, Declarator &D) { + if (D.isDeclarationOfFunction()) { + CurType = S.Context.getAttributedType(AttributedType::attr_lifetimebound, + CurType, CurType); } else { - Attr.diagnoseAppertainsTo(State.getSema(), nullptr); + Attr.diagnoseAppertainsTo(S, nullptr); } } @@ -7313,8 +7309,11 @@ static void processTypeAttrs(TypeProcess attr.setUsedAsTypeAttr(); break; case ParsedAttr::AT_LifetimeBound: - if (TAL == TAL_DeclChunk) - HandleLifetimeBoundAttr(state, type, attr); + if (TAL == TAL_DeclChunk) { + HandleLifetimeBoundAttr(type, attr, state.getSema(), + state.getDeclarator()); + attr.setUsedAsTypeAttr(); + } break; MS_TYPE_ATTRS_CASELIST: @@ -7338,10 +7337,11 @@ static void processTypeAttrs(TypeProcess bool allowOnArrayType = state.getDeclarator().isPrototypeContext() && !hasOuterPointerLikeChunk(state.getDeclarator(), endIndex); - if (checkNullabilityTypeSpecifier( - state, + if (state.getSema().checkNullabilityTypeSpecifier( type, - attr, + mapNullabilityAttrKind(attr.getKind()), + attr.getLoc(), + attr.isContextSensitiveKeywordAttribute(), allowOnArrayType)) { attr.setInvalid(); } @@ -7368,8 +7368,9 @@ static void processTypeAttrs(TypeProcess } // Apply it regardless. - if (checkObjCKindOfType(state, type, attr)) + if (state.getSema().checkObjCKindOfType(type, attr.getLoc())) attr.setInvalid(); + attr.setUsedAsTypeAttr(); break; FUNCTION_TYPE_ATTRS_CASELIST: Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Aug 13 18:55:37 2018 @@ -6058,11 +6058,6 @@ QualType TreeTransform<Derived>::Transfo if (modifiedType.isNull()) return QualType(); - const Attr *oldAttr = TL.getAttr(); - const Attr *newAttr = getDerived().TransformAttr(oldAttr); - if (!newAttr) - return QualType(); - QualType result = TL.getType(); // FIXME: dependent operand expressions? @@ -6079,20 +6074,26 @@ QualType TreeTransform<Derived>::Transfo // type sugar, and therefore cannot be diagnosed in any other way. if (auto nullability = oldType->getImmediateNullability()) { if (!modifiedType->canHaveNullability()) { - SemaRef.Diag(TL.getAttr()->getLocation(), - diag::err_nullability_nonpointer) - << DiagNullabilityKind(*nullability, false) << modifiedType; + SemaRef.Diag(TL.getAttrNameLoc(), diag::err_nullability_nonpointer) + << DiagNullabilityKind(*nullability, false) << modifiedType; return QualType(); } } - result = SemaRef.Context.getAttributedType(newAttr->getKind(), + result = SemaRef.Context.getAttributedType(oldType->getAttrKind(), modifiedType, equivalentType); } AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result); - newTL.setAttr(newAttr); + newTL.setAttrNameLoc(TL.getAttrNameLoc()); + if (TL.hasAttrOperand()) + newTL.setAttrOperandParensRange(TL.getAttrOperandParensRange()); + if (TL.hasAttrExprOperand()) + newTL.setAttrExprOperand(TL.getAttrExprOperand()); + else if (TL.hasAttrEnumOperand()) + newTL.setAttrEnumOperandLoc(TL.getAttrEnumOperandLoc()); + return result; } Modified: cfe/trunk/lib/Serialization/ASTReader.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Aug 13 18:55:37 2018 @@ -6455,10 +6455,6 @@ class TypeLocReader : public TypeLocVisi return Reader->ReadNestedNameSpecifierLoc(*F, Record, Idx); } - Attr *ReadAttr() { - return Reader->ReadAttr(*F, Record, Idx); - } - public: TypeLocReader(ModuleFile &F, ASTReader &Reader, const ASTReader::RecordData &Record, unsigned &Idx) @@ -6650,7 +6646,20 @@ void TypeLocReader::VisitEnumTypeLoc(Enu } void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) { - TL.setAttr(ReadAttr()); + TL.setAttrNameLoc(ReadSourceLocation()); + if (TL.hasAttrOperand()) { + SourceRange range; + range.setBegin(ReadSourceLocation()); + range.setEnd(ReadSourceLocation()); + TL.setAttrOperandParensRange(range); + } + if (TL.hasAttrExprOperand()) { + if (Record[Idx++]) + TL.setAttrExprOperand(Reader->ReadExpr(*F)); + else + TL.setAttrExprOperand(nullptr); + } else if (TL.hasAttrEnumOperand()) + TL.setAttrEnumOperandLoc(ReadSourceLocation()); } void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Aug 13 18:55:37 2018 @@ -2648,72 +2648,19 @@ void ASTDeclReader::VisitOMPCapturedExpr // Attribute Reading //===----------------------------------------------------------------------===// -namespace { -class AttrReader { - ModuleFile *F; - ASTReader *Reader; - const ASTReader::RecordData &Record; - unsigned &Idx; - -public: - AttrReader(ModuleFile &F, ASTReader &Reader, - const ASTReader::RecordData &Record, unsigned &Idx) - : F(&F), Reader(&Reader), Record(Record), Idx(Idx) {} - - const uint64_t &readInt() { return Record[Idx++]; } - - SourceRange readSourceRange() { - return Reader->ReadSourceRange(*F, Record, Idx); - } - - Expr *readExpr() { return Reader->ReadExpr(*F); } - - std::string readString() { - return Reader->ReadString(Record, Idx); - } - - TypeSourceInfo *getTypeSourceInfo() { - return Reader->GetTypeSourceInfo(*F, Record, Idx); - } - - IdentifierInfo *getIdentifierInfo() { - return Reader->GetIdentifierInfo(*F, Record, Idx); - } - - VersionTuple readVersionTuple() { - return ASTReader::ReadVersionTuple(Record, Idx); - } - - template <typename T> T *GetLocalDeclAs(uint32_t LocalID) { - return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID)); - } -}; -} - -Attr *ASTReader::ReadAttr(ModuleFile &M, const RecordData &Rec, - unsigned &Idx) { - AttrReader Record(M, *this, Rec, Idx); - auto V = Record.readInt(); - if (!V) - return nullptr; - - Attr *New = nullptr; - // Kind is stored as a 1-based integer because 0 is used to indicate a null - // Attr pointer. - auto Kind = static_cast<attr::Kind>(V - 1); - SourceRange Range = Record.readSourceRange(); - ASTContext &Context = getContext(); +/// Reads attributes from the current stream position. +void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) { + for (unsigned i = 0, e = Record.readInt(); i != e; ++i) { + Attr *New = nullptr; + auto Kind = (attr::Kind)Record.readInt(); + SourceRange Range = Record.readSourceRange(); + ASTContext &Context = getContext(); #include "clang/Serialization/AttrPCHRead.inc" - assert(New && "Unable to decode attribute?"); - return New; -} - -/// Reads attributes from the current stream position. -void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) { - for (unsigned I = 0, E = Record.readInt(); I != E; ++I) - Attrs.push_back(Record.readAttr()); + assert(New && "Unable to decode attribute?"); + Attrs.push_back(New); + } } //===----------------------------------------------------------------------===// Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Aug 13 18:55:37 2018 @@ -770,7 +770,19 @@ void TypeLocWriter::VisitEnumTypeLoc(Enu } void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) { - Record.AddAttr(TL.getAttr()); + Record.AddSourceLocation(TL.getAttrNameLoc()); + if (TL.hasAttrOperand()) { + SourceRange range = TL.getAttrOperandParensRange(); + Record.AddSourceLocation(range.getBegin()); + Record.AddSourceLocation(range.getEnd()); + } + if (TL.hasAttrExprOperand()) { + Expr *operand = TL.getAttrExprOperand(); + Record.push_back(operand ? 1 : 0); + if (operand) Record.AddStmt(operand); + } else if (TL.hasAttrEnumOperand()) { + Record.AddSourceLocation(TL.getAttrEnumOperandLoc()); + } } void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { @@ -4469,21 +4481,16 @@ void ASTWriter::WriteModuleFileExtension // General Serialization Routines //===----------------------------------------------------------------------===// -void ASTRecordWriter::AddAttr(const Attr *A) { +/// Emit the list of attributes to the specified record. +void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) { auto &Record = *this; - if (!A) - return Record.push_back(0); - Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs - Record.AddSourceRange(A->getRange()); + Record.push_back(Attrs.size()); + for (const auto *A : Attrs) { + Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs + Record.AddSourceRange(A->getRange()); #include "clang/Serialization/AttrPCHWrite.inc" -} - -/// Emit the list of attributes to the specified record. -void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) { - push_back(Attrs.size()); - for (const auto *A : Attrs) - AddAttr(A); + } } void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) { Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp Mon Aug 13 18:55:37 2018 @@ -103,9 +103,9 @@ Nullability getNullabilityAnnotation(Qua const auto *AttrType = Type->getAs<AttributedType>(); if (!AttrType) return Nullability::Unspecified; - if (AttrType->getAttrKind() == attr::TypeNullable) + if (AttrType->getAttrKind() == AttributedType::attr_nullable) return Nullability::Nullable; - else if (AttrType->getAttrKind() == attr::TypeNonNull) + else if (AttrType->getAttrKind() == AttributedType::attr_nonnull) return Nullability::Nonnull; return Nullability::Unspecified; } Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=339638&r1=339637&r2=339638&view=diff ============================================================================== --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original) +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Mon Aug 13 18:55:37 2018 @@ -2470,10 +2470,8 @@ namespace { static const AttrClassDescriptor AttrClassDescriptors[] = { { "ATTR", "Attr" }, - { "TYPE_ATTR", "TypeAttr" }, { "STMT_ATTR", "StmtAttr" }, { "INHERITABLE_ATTR", "InheritableAttr" }, - { "DECL_OR_TYPE_ATTR", "DeclOrTypeAttr" }, { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" }, { "PARAMETER_ABI_ATTR", "ParameterABIAttr" } }; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits