llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-libcxx Author: Yash Verma (My-Bad-2) <details> <summary>Changes</summary> This PR implements the compiler built-in and standard library interfaces for C++23 Explicit Lifetime Management as proposed in [P2590R2](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2590r2.pdf) and fixed for arrays in [P2679R2](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2679r2.pdf). This PR implements a `__builtin_start_lifetime_as((T*)ptr)` builtin which is used by `std::start_lifetime_as<T>(ptr)` and `std::start_lifetime_as_array<T>(ptr, n)`. I'm sorry if there are any mistakes in the pull request as this my first PR ever. Also, the commit timestamp is a bit messed up because I forgot to run `git clang-format` hook before pushing a few commits to the remote host. --- Patch is 209.42 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/196286.diff 17 Files Affected: - (modified) clang/include/clang/AST/TypeBase.h (+304-385) - (modified) clang/include/clang/Basic/Builtins.td (+6) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3) - (modified) clang/include/clang/Sema/Sema.h (+7) - (modified) clang/lib/AST/ExprConstant.cpp (+6) - (modified) clang/lib/AST/Type.cpp (+51) - (modified) clang/lib/CodeGen/CGBuiltin.cpp (+265-261) - (modified) clang/lib/Sema/SemaChecking.cpp (+463-396) - (added) clang/test/CodeGenCXX/builtin-start-lifetime-as.cpp (+13) - (added) clang/test/SemaCXX/builtin-start-lifetime-as.cpp (+56) - (modified) libcxx/include/CMakeLists.txt (+1) - (added) libcxx/include/__memory/start_lifetime_as.h (+72) - (modified) libcxx/include/memory (+26) - (modified) libcxx/include/module.modulemap.in (+1) - (added) libcxx/test/std/memory/start.lifetime/start_lifetime_as.pass.cpp (+76) - (added) libcxx/test/std/memory/start.lifetime/start_lifetime_as.verify.cpp (+35) - (added) libcxx/test/std/memory/start.lifetime/start_lifetime_as_array.pass.cpp (+47) ``````````diff diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index b2887bcc36246..2e20cecd8ae1d 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -71,43 +71,37 @@ class TemplateParameterList; class Type; class Attr; -enum { - TypeAlignmentInBits = 4, - TypeAlignment = 1 << TypeAlignmentInBits -}; +enum { TypeAlignmentInBits = 4, TypeAlignment = 1 << TypeAlignmentInBits }; namespace serialization { - template <class T> class AbstractTypeReader; - template <class T> class AbstractTypeWriter; -} +template <class T> class AbstractTypeReader; +template <class T> class AbstractTypeWriter; +} // namespace serialization } // namespace clang namespace llvm { - template <typename T> - struct PointerLikeTypeTraits; - template<> - struct PointerLikeTypeTraits< ::clang::Type*> { - static inline void *getAsVoidPointer(::clang::Type *P) { return P; } +template <typename T> struct PointerLikeTypeTraits; +template <> struct PointerLikeTypeTraits<::clang::Type *> { + static inline void *getAsVoidPointer(::clang::Type *P) { return P; } - static inline ::clang::Type *getFromVoidPointer(void *P) { - return static_cast< ::clang::Type*>(P); - } + static inline ::clang::Type *getFromVoidPointer(void *P) { + return static_cast<::clang::Type *>(P); + } - static constexpr int NumLowBitsAvailable = clang::TypeAlignmentInBits; - }; + static constexpr int NumLowBitsAvailable = clang::TypeAlignmentInBits; +}; - template<> - struct PointerLikeTypeTraits< ::clang::ExtQuals*> { - static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; } +template <> struct PointerLikeTypeTraits<::clang::ExtQuals *> { + static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; } - static inline ::clang::ExtQuals *getFromVoidPointer(void *P) { - return static_cast< ::clang::ExtQuals*>(P); - } + static inline ::clang::ExtQuals *getFromVoidPointer(void *P) { + return static_cast<::clang::ExtQuals *>(P); + } - static constexpr int NumLowBitsAvailable = clang::TypeAlignmentInBits; - }; + static constexpr int NumLowBitsAvailable = clang::TypeAlignmentInBits; +}; } // namespace llvm @@ -339,11 +333,7 @@ class Qualifiers { CVRMask = Const | Volatile | Restrict }; - enum GC { - GCNone = 0, - Weak, - Strong - }; + enum GC { GCNone = 0, Weak, Strong }; enum ObjCLifetime { /// There is no lifetime qualification on this type. @@ -496,9 +486,7 @@ class Qualifiers { assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); Mask &= ~static_cast<uint64_t>(mask); } - void removeCVRQualifiers() { - removeCVRQualifiers(CVRMask); - } + void removeCVRQualifiers() { removeCVRQualifiers(CVRMask); } void addCVRQualifiers(unsigned mask) { assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); Mask |= mask; @@ -509,9 +497,7 @@ class Qualifiers { } bool hasUnaligned() const { return Mask & UMask; } - void setUnaligned(bool flag) { - Mask = (Mask & ~UMask) | (flag ? UMask : 0); - } + void setUnaligned(bool flag) { Mask = (Mask & ~UMask) | (flag ? UMask : 0); } void removeUnaligned() { Mask &= ~UMask; } void addUnaligned() { Mask |= UMask; } @@ -590,8 +576,8 @@ class Qualifiers { } void setAddressSpace(LangAS space) { assert((unsigned)space <= MaxAddressSpace); - Mask = (Mask & ~AddressSpaceMask) - | (((uint32_t) space) << AddressSpaceShift); + Mask = + (Mask & ~AddressSpaceMask) | (((uint32_t)space) << AddressSpaceShift); } void removeAddressSpace() { setAddressSpace(LangAS::Default); } void addAddressSpace(LangAS space) { @@ -625,9 +611,7 @@ class Qualifiers { assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); Mask &= ~static_cast<uint64_t>(mask); } - void removeFastQualifiers() { - removeFastQualifiers(FastMask); - } + void removeFastQualifiers() { removeFastQualifiers(FastMask); } void addFastQualifiers(unsigned mask) { assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); Mask |= mask; @@ -687,12 +671,12 @@ class Qualifiers { /// Add the qualifiers from the given set to this set, given that /// they don't conflict. void addConsistentQualifiers(Qualifiers qs) { - assert(getAddressSpace() == qs.getAddressSpace() || - !hasAddressSpace() || !qs.hasAddressSpace()); - assert(getObjCGCAttr() == qs.getObjCGCAttr() || - !hasObjCGCAttr() || !qs.hasObjCGCAttr()); - assert(getObjCLifetime() == qs.getObjCLifetime() || - !hasObjCLifetime() || !qs.hasObjCLifetime()); + assert(getAddressSpace() == qs.getAddressSpace() || !hasAddressSpace() || + !qs.hasAddressSpace()); + assert(getObjCGCAttr() == qs.getObjCGCAttr() || !hasObjCGCAttr() || + !qs.hasObjCGCAttr()); + assert(getObjCLifetime() == qs.getObjCLifetime() || !hasObjCLifetime() || + !qs.hasObjCLifetime()); assert(!hasPointerAuth() || !qs.hasPointerAuth() || getPointerAuth() == qs.getPointerAuth()); Mask |= qs.Mask; @@ -880,7 +864,7 @@ struct SplitQualType { SplitQualType getSingleStepDesugaredType() const; // end of this file // Make std::tie work. - std::pair<const Type *,Qualifiers> asPair() const { + std::pair<const Type *, Qualifiers> asPair() const { return std::pair<const Type *, Qualifiers>(Ty, Quals); } @@ -939,7 +923,8 @@ class QualType { // Thankfully, these are efficiently composable. llvm::PointerIntPair<llvm::PointerUnion<const Type *, const ExtQuals *>, - Qualifiers::FastWidth> Value; + Qualifiers::FastWidth> + Value; const ExtQuals *getExtQualsUnsafe() const { return cast<const ExtQuals *>(Value.getPointer()); @@ -953,7 +938,7 @@ class QualType { assert(!isNull() && "Cannot retrieve a NULL type pointer"); auto CommonPtrVal = reinterpret_cast<uintptr_t>(Value.getOpaqueValue()); CommonPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1); - return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal); + return reinterpret_cast<ExtQualsTypeCommonBase *>(CommonPtrVal); } public: @@ -985,25 +970,19 @@ class QualType { static QualType getFromOpaquePtr(const void *Ptr) { QualType T; - T.Value.setFromOpaqueValue(const_cast<void*>(Ptr)); + T.Value.setFromOpaqueValue(const_cast<void *>(Ptr)); return T; } - const Type &operator*() const { - return *getTypePtr(); - } + const Type &operator*() const { return *getTypePtr(); } - const Type *operator->() const { - return getTypePtr(); - } + const Type *operator->() const { return getTypePtr(); } bool isCanonical() const; bool isCanonicalAsParam() const; /// Return true if this QualType doesn't point to a type yet. - bool isNull() const { - return Value.getPointer().isNull(); - } + bool isNull() const { return Value.getPointer().isNull(); } // Determines if a type can form `T&`. bool isReferenceable() const; @@ -1086,15 +1065,13 @@ class QualType { /// Retrieve the set of CVR (const-volatile-restrict) qualifiers /// local to this particular QualType instance, not including any qualifiers /// acquired through typedefs or other sugar. - unsigned getLocalCVRQualifiers() const { - return getLocalFastQualifiers(); - } + unsigned getLocalCVRQualifiers() const { return getLocalFastQualifiers(); } /// Retrieve the set of CVR (const-volatile-restrict) qualifiers /// applied to this type. unsigned getCVRQualifiers() const; - bool isConstant(const ASTContext& Ctx) const { + bool isConstant(const ASTContext &Ctx) const { return QualType::isConstant(*this, Ctx); } @@ -1164,25 +1141,17 @@ class QualType { // easily added. /// Add the `const` type qualifier to this QualType. - void addConst() { - addFastQualifiers(Qualifiers::Const); - } - QualType withConst() const { - return withFastQualifiers(Qualifiers::Const); - } + void addConst() { addFastQualifiers(Qualifiers::Const); } + QualType withConst() const { return withFastQualifiers(Qualifiers::Const); } /// Add the `volatile` type qualifier to this QualType. - void addVolatile() { - addFastQualifiers(Qualifiers::Volatile); - } + void addVolatile() { addFastQualifiers(Qualifiers::Volatile); } QualType withVolatile() const { return withFastQualifiers(Qualifiers::Volatile); } /// Add the `restrict` qualifier to this QualType. - void addRestrict() { - addFastQualifiers(Qualifiers::Restrict); - } + void addRestrict() { addFastQualifiers(Qualifiers::Restrict); } QualType withRestrict() const { return withFastQualifiers(Qualifiers::Restrict); } @@ -1192,8 +1161,8 @@ class QualType { } void addFastQualifiers(unsigned TQs) { - assert(!(TQs & ~Qualifiers::FastMask) - && "non-fast qualifier bits set in mask!"); + assert(!(TQs & ~Qualifiers::FastMask) && + "non-fast qualifier bits set in mask!"); Value.setInt(Value.getInt() | TQs); } @@ -1360,9 +1329,8 @@ class QualType { return print(split.Ty, split.Quals, OS, policy, PlaceHolder, Indentation); } - static void print(const Type *ty, Qualifiers qs, - raw_ostream &OS, const PrintingPolicy &policy, - const Twine &PlaceHolder, + static void print(const Type *ty, Qualifiers qs, raw_ostream &OS, + const PrintingPolicy &policy, const Twine &PlaceHolder, unsigned Indentation = 0); void getAsStringInternal(std::string &Str, @@ -1436,14 +1404,10 @@ class QualType { inline Qualifiers::GC getObjCGCAttr() const; /// true when Type is objc's weak. - bool isObjCGCWeak() const { - return getObjCGCAttr() == Qualifiers::Weak; - } + bool isObjCGCWeak() const { return getObjCGCAttr() == Qualifiers::Weak; } /// true when Type is objc's strong. - bool isObjCGCStrong() const { - return getObjCGCAttr() == Qualifiers::Strong; - } + bool isObjCGCStrong() const { return getObjCGCAttr() == Qualifiers::Strong; } /// Returns lifetime attribute of this type. Qualifiers::ObjCLifetime getObjCLifetime() const { @@ -1599,8 +1563,7 @@ class QualType { /// \param context The context in which the subject type was written. /// /// \returns the resulting type. - QualType substObjCTypeArgs(ASTContext &ctx, - ArrayRef<QualType> typeArgs, + QualType substObjCTypeArgs(ASTContext &ctx, ArrayRef<QualType> typeArgs, ObjCSubstitutionContext context) const; /// Substitute type arguments from an object type for the Objective-C type @@ -1623,8 +1586,7 @@ class QualType { /// /// \returns the subject type after replacing all of the Objective-C type /// parameters with their corresponding arguments. - QualType substObjCMemberType(QualType objectType, - const DeclContext *dc, + QualType substObjCMemberType(QualType objectType, const DeclContext *dc, ObjCSubstitutionContext context) const; /// Strip Objective-C "__kindof" types from the given type. @@ -1641,7 +1603,7 @@ class QualType { // These methods are implemented in a separate translation unit; // "static"-ize them to avoid creating temporary QualTypes in the // caller. - static bool isConstant(QualType T, const ASTContext& Ctx); + static bool isConstant(QualType T, const ASTContext &Ctx); static QualType getDesugaredType(QualType T, const ASTContext &Context); static SplitQualType getSplitDesugaredType(QualType T); static SplitQualType getSplitUnqualifiedTypeImpl(QualType type); @@ -1651,7 +1613,8 @@ class QualType { static DestructionKind isDestructedTypeImpl(QualType type); /// Check if \param RD is or contains a non-trivial C union. - static bool hasNonTrivialToPrimitiveDefaultInitializeCUnion(const RecordDecl *RD); + static bool + hasNonTrivialToPrimitiveDefaultInitializeCUnion(const RecordDecl *RD); static bool hasNonTrivialToPrimitiveDestructCUnion(const RecordDecl *RD); static bool hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD); }; @@ -1664,7 +1627,7 @@ namespace llvm { /// Implement simplify_type for QualType, so that we can dyn_cast from QualType /// to a specific Type class. -template<> struct simplify_type< ::clang::QualType> { +template <> struct simplify_type<::clang::QualType> { using SimpleType = const ::clang::Type *; static SimpleType getSimplifiedValue(::clang::QualType Val) { @@ -1673,8 +1636,7 @@ template<> struct simplify_type< ::clang::QualType> { }; // Teach SmallPtrSet that QualType is "basically a pointer". -template<> -struct PointerLikeTypeTraits<clang::QualType> { +template <> struct PointerLikeTypeTraits<clang::QualType> { static inline void *getAsVoidPointer(clang::QualType P) { return P.getAsOpaquePtr(); } @@ -1750,10 +1712,10 @@ class alignas(TypeAlignment) ExtQuals : public ExtQualsTypeCommonBase, : ExtQualsTypeCommonBase(baseType, canon.isNull() ? QualType(this_(), 0) : canon), Quals(quals) { - assert(Quals.hasNonFastQualifiers() - && "ExtQuals created with no fast qualifiers"); - assert(!Quals.hasFastQualifiers() - && "ExtQuals created with fast qualifiers"); + assert(Quals.hasNonFastQualifiers() && + "ExtQuals created with no fast qualifiers"); + assert(!Quals.hasFastQualifiers() && + "ExtQuals created with fast qualifiers"); } Qualifiers getQualifiers() const { return Quals; } @@ -1776,8 +1738,7 @@ class alignas(TypeAlignment) ExtQuals : public ExtQualsTypeCommonBase, Profile(ID, getBaseType(), Quals); } - static void Profile(llvm::FoldingSetNodeID &ID, - const Type *BaseType, + static void Profile(llvm::FoldingSetNodeID &ID, const Type *BaseType, Qualifiers Quals) { assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!"); ID.AddPointer(BaseType); @@ -1908,9 +1869,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { LLVM_PREFERRED_TYPE(bool) mutable unsigned FromAST : 1; - bool isCacheValid() const { - return CacheValid; - } + bool isCacheValid() const { return CacheValid; } Linkage getLinkage() const { assert(isCacheValid() && "getting linkage from invalid cache"); @@ -2392,9 +2351,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { template <class T> friend class TypePropertyCache; /// Set whether this type comes from an AST file. - void setFromAST(bool V = true) const { - TypeBits.FromAST = V; - } + void setFromAST(bool V = true) const { TypeBits.FromAST = V; } protected: friend class ASTContext; @@ -2533,11 +2490,13 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { /// class), will be set to the declaration. bool isIncompleteType(NamedDecl **Def = nullptr) const; + /// Determines if this type is an implicit-lifetime type as defined in C++20 + /// [basic.types.general]. Returns true if the type is implicit lifetime type. + bool isImplicitLifetimeType() const; + /// Return true if this is an incomplete or object /// type, in other words, not a function type. - bool isIncompleteOrObjectType() const { - return !isFunctionType(); - } + bool isIncompleteOrObjectType() const { return !isFunctionType(); } /// \returns True if the type is incomplete and it is also a type that /// cannot be completed by a later type definition. @@ -2602,7 +2561,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { /// isIntegerType() does *not* include complex integers (a GCC extension). /// isComplexIntegerType() can be used to test for complex integers. - bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum) + bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum) bool isEnumeralType() const; /// Determine whether this type is a scoped enumeration type. @@ -2628,21 +2587,21 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double) /// isComplexType() does *not* include complex integers (a GCC extension). /// isComplexIntegerType() can be used to test for complex integers. - bool isComplexType() const; // C99 6.2.5p11 (complex) - bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int. - bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) - bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) - bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661 + bool isComplexType() const; // C99 6.2.5p11 (complex) + bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int. + bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) + bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) + bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661 bool isFloat32Type() const; bool isDoubleType() const; bool isBFloat16Type() const; bool isMFloat8Type() const; bool isFloat128Type() const; bool isIbm128Type() const; - bool isRealType() const; // C99 6.2.5p17 (real floating + integer) - bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) - bool isVoidType() const; // C99 6.2.5p19 - bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers) + bool isRealType() const; // C99 6.2.5p17 (real floating + integer) + bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) + bool isVoidType() const; // C99 6.2.5p19 + bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers) bool isAggregateType() const; bool isFundamentalType() const; bool isCompoundType() const; @@ -2657,7 +2616,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isSignableType(const ASTContext &Ctx) const; bool isSignablePointerType() const; bool isSignableIntegerType(const ASTContext &Ctx) const; - bool isAnyPointerType() const; // Any C pointer or ObjC object pointer + bool isAnyPointerType() const; // Any C pointer or ObjC object pointer bool isCountAttributedType() const; bool isCFIUncheckedCalleeFunctionType() const; bool hasPointeeToCFIUncheckedCalleeFunctionType() const; @@ -2686,33 +2645,35 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isInterfaceType() const; bool isStructureOrClassType() const; bool isUnionType() const; - bool isComplexIntegerType() const; // GCC _Complex integer type. - bool isVectorType() const; // GCC vector type. - bool isExtVectorType() const; // Extended vector type. - bool isExtVectorBoolType() const; // Extended vector type with bool element. + bool isComplexIntegerType() const; // GCC _Complex integer type. + bool isVectorType() const; // GCC vector type. + bool isExtVectorType() const; // Extended vector type. + bool isExtVectorBoolType() const; // Extended vector type with bool element. bool isConstantMatrixBoolType() const; // Matrix type with bool element. // Extended vector type with bool element that is packed. HLSL doesn't pack // its bool vectors. bool isPackedVectorBoolType(const ASTContext &ctx) const; bool isSubscriptableVectorType() const; - bool isMatrixType() const; // Matrix type. - bool isConstantMatrixType() const; // Constant matrix type. - bool isOverflowBehaviorType() const; // Overflow behavior type. - bool isDependentAddressSpaceType() const; // value-dependent address space qualifier - bool isObjCObjectPointerType() const; // pointer to ObjC object - bool isObjCRetainableType() const; // ObjC object or block pointer - bool isObjCLifetimeType() const; // (array of)* retainable type - bool isObjCIndirectLifetimeType() const; // (pointer to)* lifetime type - bool isObjCNSObjectType() const; // __attribute__((NSObject)) - bool isObjCIndependentClassType() cons... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/196286 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
