diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -86,7 +86,7 @@ return (std::numeric_limits::max() >> NumLowBitsAvailable) - 1; } - static constexpr int NumLowBitsAvailable = 3; + static constexpr int NumLowBitsAvailable = 4; }; } @@ -100,7 +100,7 @@ } // Validated by static_assert in APValue.cpp; hardcoded to avoid needing // to include Type.h. - static constexpr int NumLowBitsAvailable = 3; + static constexpr int NumLowBitsAvailable = 4; }; template<> struct PointerLikeTypeTraits { diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h --- a/clang/include/clang/AST/CanonicalType.h +++ b/clang/include/clang/AST/CanonicalType.h @@ -146,6 +146,10 @@ return Stored.isLocalRestrictQualified(); } + bool isOptionalQualified() const { + return Stored.isLocalOptionalQualified(); + } + /// Determines if this canonical type is furthermore /// canonical as a parameter. The parameter-canonicalization /// process decays arrays to pointers and drops top-level qualifiers. diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -65,7 +65,7 @@ class Type; enum { - TypeAlignmentInBits = 4, + TypeAlignmentInBits = 5, TypeAlignment = 1 << TypeAlignmentInBits }; @@ -149,7 +149,8 @@ Const = 0x1, Restrict = 0x2, Volatile = 0x4, - CVRMask = Const | Volatile | Restrict + Optional = 0x8, + CVRMask = Const | Volatile | Restrict | Optional }; enum GC { @@ -186,7 +187,7 @@ MaxAddressSpace = 0x7fffffu, /// The width of the "fast" qualifier mask. - FastWidth = 3, + FastWidth = 4, /// The fast qualifier mask. FastMask = (1 << FastWidth) - 1 @@ -280,6 +281,16 @@ return Qs; } + bool hasOptional() const { return Mask & Optional; } + bool hasOnlyOptional() const { return Mask == Optional; } + void removeOptional() { Mask &= ~Optional; } + void addOptional() { Mask |= Optional; } + Qualifiers withOptional() const { + Qualifiers Qs = *this; + Qs.addOptional(); + return Qs; + } + bool hasRestrict() const { return Mask & Restrict; } bool hasOnlyRestrict() const { return Mask == Restrict; } void removeRestrict() { Mask &= ~Restrict; } @@ -608,19 +619,19 @@ } private: - // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31| - // |C R V|U|GCAttr|Lifetime|AddressSpace| + // bits: |0 1 2 3|4|5 .. 6|7 .. 9|10 ... 31| + // |C R V O|U|GCAttr|Lifetime|AddressSpace| uint32_t Mask = 0; - static const uint32_t UMask = 0x8; - static const uint32_t UShift = 3; - static const uint32_t GCAttrMask = 0x30; - static const uint32_t GCAttrShift = 4; - static const uint32_t LifetimeMask = 0x1C0; - static const uint32_t LifetimeShift = 6; + static const uint32_t UMask = 0x10; + static const uint32_t UShift = 4; + static const uint32_t GCAttrMask = 0x60; + static const uint32_t GCAttrShift = 5; + static const uint32_t LifetimeMask = 0x380; + static const uint32_t LifetimeShift = 7; static const uint32_t AddressSpaceMask = ~(CVRMask | UMask | GCAttrMask | LifetimeMask); - static const uint32_t AddressSpaceShift = 9; + static const uint32_t AddressSpaceShift = 10; }; class QualifiersAndAtomic { @@ -635,16 +646,19 @@ operator Qualifiers() const { return Quals; } bool hasVolatile() const { return Quals.hasVolatile(); } + bool hasOptional() const { return Quals.hasOptional(); } bool hasConst() const { return Quals.hasConst(); } bool hasRestrict() const { return Quals.hasRestrict(); } bool hasAtomic() const { return HasAtomic; } void addVolatile() { Quals.addVolatile(); } + void addOptional() { Quals.addOptional(); } void addConst() { Quals.addConst(); } void addRestrict() { Quals.addRestrict(); } void addAtomic() { HasAtomic = true; } void removeVolatile() { Quals.removeVolatile(); } + void removeOptional() { Quals.removeOptional(); } void removeConst() { Quals.removeConst(); } void removeRestrict() { Quals.removeRestrict(); } void removeAtomic() { HasAtomic = false; } @@ -652,6 +666,9 @@ QualifiersAndAtomic withVolatile() { return {Quals.withVolatile(), HasAtomic}; } + QualifiersAndAtomic withOptional() { + return {Quals.withOptional(), HasAtomic}; + } QualifiersAndAtomic withConst() { return {Quals.withConst(), HasAtomic}; } QualifiersAndAtomic withRestrict() { return {Quals.withRestrict(), HasAtomic}; @@ -837,6 +854,16 @@ /// Determine whether this type is volatile-qualified. bool isVolatileQualified() const; + /// Determine whether this particular QualType instance has the + /// "_Optional" qualifier set, without looking through typedefs that may have + /// added "_Optional" at a different level. + bool isLocalOptionalQualified() const { + return (getLocalFastQualifiers() & Qualifiers::Optional); + } + + /// Determine whether this type is _Optional-qualified. + bool isOptionalQualified() const; + /// Determine whether this particular QualType instance has any /// qualifiers, without looking through any typedefs that might add /// qualifiers at a different level. @@ -924,6 +951,13 @@ return withFastQualifiers(Qualifiers::Volatile); } + /// Add the `_Optional` type qualifier to this QualType. + void addOptional() { + addFastQualifiers(Qualifiers::Optional); + } + QualType withOptional() const { + return withFastQualifiers(Qualifiers::Optional); + } /// Add the `restrict` qualifier to this QualType. void addRestrict() { addFastQualifiers(Qualifiers::Restrict); @@ -944,6 +978,7 @@ void removeLocalConst(); void removeLocalVolatile(); + void removeLocalOptional(); void removeLocalRestrict(); void removeLocalCVRQualifiers(unsigned Mask); @@ -1563,7 +1598,7 @@ /// /// Types, once created, are immutable. /// -class alignas(8) Type : public ExtQualsTypeCommonBase { +class alignas(16) Type : public ExtQualsTypeCommonBase { public: enum TypeClass { #define TYPE(Class, Base) Class, @@ -1950,7 +1985,7 @@ Type(TypeClass tc, QualType canon, TypeDependence Dependence) : ExtQualsTypeCommonBase(this, canon.isNull() ? QualType(this_(), 0) : canon) { - static_assert(sizeof(*this) <= 8 + sizeof(ExtQualsTypeCommonBase), + static_assert(sizeof(*this) <= 16 + sizeof(ExtQualsTypeCommonBase), "changing bitfields changed sizeof(Type)!"); static_assert(alignof(decltype(*this)) % sizeof(void *) == 0, "Insufficient alignment!"); @@ -3962,6 +3997,7 @@ bool isConst() const { return getFastTypeQuals().hasConst(); } bool isVolatile() const { return getFastTypeQuals().hasVolatile(); } + bool isOptional() const { return getFastTypeQuals().hasOptional(); } bool isRestrict() const { return getFastTypeQuals().hasRestrict(); } /// Determine the type of an expression that calls a function of @@ -6718,6 +6754,11 @@ getCommonPtr()->CanonicalType.isLocalVolatileQualified(); } +inline bool QualType::isOptionalQualified() const { + return isLocalOptionalQualified() || + getCommonPtr()->CanonicalType.isLocalOptionalQualified(); +} + inline bool QualType::hasQualifiers() const { return hasLocalQualifiers() || getCommonPtr()->CanonicalType.hasLocalQualifiers(); @@ -6749,6 +6790,10 @@ removeLocalFastQualifiers(Qualifiers::Volatile); } +inline void QualType::removeLocalOptional() { + removeLocalFastQualifiers(Qualifiers::Optional); +} + inline void QualType::removeLocalCVRQualifiers(unsigned Mask) { assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-CVR bits"); static_assert((int)Qualifiers::CVRMask == (int)Qualifiers::FastMask, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1904,7 +1904,10 @@ def err_member_function_call_bad_cvr : Error< "'this' argument to member function %0 has type %1, but function is not marked " "%select{const|restrict|const or restrict|volatile|const or volatile|" - "volatile or restrict|const, volatile, or restrict}2">; + "volatile or restrict|const, volatile, or restrict|_Optional|" + "const or _Optional|restrict or _Optional|const, restrict or _Optional|" + "volatile or _Optional|const, volatile or _Optional|" + "volatile, restrict or _Optional|const, volatile, restrict or _Optional}2">; def err_member_function_call_bad_ref : Error< "'this' argument to member function %0 is an %select{lvalue|rvalue}1, " "but function has %select{non-const lvalue|rvalue}2 ref-qualifier">; @@ -4653,13 +4656,19 @@ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "'this' argument has type %3, but method is not marked " "%select{const|restrict|const or restrict|volatile|const or volatile|" - "volatile or restrict|const, volatile, or restrict}4">; + "volatile or restrict|const, volatile, or restrict|_Optional|" + "const or _Optional|restrict or _Optional|const, restrict or _Optional|" + "volatile or _Optional|const, volatile or _Optional|" + "volatile, restrict or _Optional|const, volatile, restrict or _Optional}4">; def note_ovl_candidate_bad_cvr : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "%ordinal5 argument (%3) would lose " "%select{const|restrict|const and restrict|volatile|const and volatile|" - "volatile and restrict|const, volatile, and restrict}4 qualifier" - "%select{||s||s|s|s}4">; + "volatile and restrict|const, volatile, and restrict|_Optional|" + "const and _Optional|restrict and _Optional|const, restrict and _Optional|" + "volatile and _Optional|const, volatile and _Optional|" + "volatile, restrict and _Optional|const, volatile, restrict and _Optional}4 qualifier" + "%select{||s||s|s|s||s|s|s|s|s|s|s}4">; def note_ovl_candidate_bad_unaligned : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "%ordinal5 argument (%3) would lose __unaligned qualifier">; diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -324,6 +324,7 @@ KEYWORD(_Generic , KEYALL) KEYWORD(_Imaginary , KEYALL) KEYWORD(_Noreturn , KEYALL) +KEYWORD(_Optional , KEYALL) KEYWORD(_Static_assert , KEYALL) KEYWORD(_Thread_local , KEYALL) KEYWORD(__func__ , KEYALL) @@ -552,6 +553,7 @@ TYPE_TRAIT_1(__is_volatile, IsVolatile, KEYCXX) TYPE_TRAIT_1(__is_signed, IsSigned, KEYCXX) TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX) +TYPE_TRAIT_1(__is_optional, IsOptional, KEYCXX) // Embarcadero Binary Type Traits TYPE_TRAIT_2(__is_same, IsSame, KEYCXX) @@ -671,6 +673,8 @@ ALIAS("__typeof__" , typeof , KEYALL) ALIAS("__volatile" , volatile , KEYALL) ALIAS("__volatile__" , volatile , KEYALL) +ALIAS("__optional" , _Optional , KEYALL) +ALIAS("__optional__" , _Optional , KEYALL) // Type nullability. KEYWORD(_Nonnull , KEYALL) diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -311,10 +311,11 @@ TQ_const = 1, TQ_restrict = 2, TQ_volatile = 4, - TQ_unaligned = 8, + TQ_optional = 8, + TQ_unaligned = 16, // This has no corresponding Qualifiers::TQ value, because it's not treated // as a qualifier in our type system. - TQ_atomic = 16 + TQ_atomic = 32 }; /// ParsedSpecifiers - Flags to query which specifiers were applied. This is @@ -396,7 +397,7 @@ /// TSTNameLoc provides source range info for tag types. SourceLocation TSTNameLoc; SourceRange TypeofParensRange; - SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc, + SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_optionalLoc, TQ_atomicLoc, TQ_unalignedLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc; SourceLocation FS_explicitCloseParenLoc; @@ -576,6 +577,7 @@ SourceLocation getConstSpecLoc() const { return TQ_constLoc; } SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; } SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; } + SourceLocation getOptionalSpecLoc() const { return TQ_optionalLoc; } SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; } SourceLocation getUnalignedSpecLoc() const { return TQ_unalignedLoc; } SourceLocation getPipeLoc() const { return TQ_pipeLoc; } @@ -586,6 +588,7 @@ TQ_constLoc = SourceLocation(); TQ_restrictLoc = SourceLocation(); TQ_volatileLoc = SourceLocation(); + TQ_optionalLoc = SourceLocation(); TQ_atomicLoc = SourceLocation(); TQ_unalignedLoc = SourceLocation(); TQ_pipeLoc = SourceLocation(); @@ -1231,6 +1234,9 @@ /// The location of the volatile-qualifier, if any. SourceLocation VolatileQualLoc; + /// The location of the _Optional-qualifier, if any. + SourceLocation OptionalQualLoc; + /// The location of the restrict-qualifier, if any. SourceLocation RestrictQualLoc; @@ -1608,6 +1614,7 @@ static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, SourceLocation ConstQualLoc, SourceLocation VolatileQualLoc, + SourceLocation OptionalQualLoc, SourceLocation RestrictQualLoc, SourceLocation AtomicQualLoc, SourceLocation UnalignedQualLoc) { @@ -1618,6 +1625,7 @@ I.Ptr.TypeQuals = TypeQuals; I.Ptr.ConstQualLoc = ConstQualLoc; I.Ptr.VolatileQualLoc = VolatileQualLoc; + I.Ptr.OptionalQualLoc = OptionalQualLoc; I.Ptr.RestrictQualLoc = RestrictQualLoc; I.Ptr.AtomicQualLoc = AtomicQualLoc; I.Ptr.UnalignedQualLoc = UnalignedQualLoc; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2874,6 +2874,7 @@ SourceLocation FallbackLoc, SourceLocation ConstQualLoc = SourceLocation(), SourceLocation VolatileQualLoc = SourceLocation(), + SourceLocation OptionalQualLoc = SourceLocation(), SourceLocation RestrictQualLoc = SourceLocation(), SourceLocation AtomicQualLoc = SourceLocation(), SourceLocation UnalignedQualLoc = SourceLocation()); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1468,7 +1468,7 @@ // See comments in InjectedClassNameType definition for details // return Importer.getToContext().getInjectedClassNameType(D, InjType); enum { - TypeAlignmentInBits = 4, + TypeAlignmentInBits = 5, TypeAlignment = 1 << TypeAlignmentInBits }; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1708,9 +1708,10 @@ Out << 'N'; if (const CXXMethodDecl *Method = dyn_cast(ND)) { Qualifiers MethodQuals = Method->getMethodQualifiers(); - // We do not consider restrict a distinguishing attribute for overloading + // We do not consider restrict or _Optional a distinguishing attribute for overloading // purposes so we must not mangle it. MethodQuals.removeRestrict(); + MethodQuals.removeOptional(); mangleQualifiers(MethodQuals); mangleRefQualifier(Method->getRefQualifier()); } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -169,6 +169,11 @@ OS << "__restrict"; } } + if (TypeQuals & Qualifiers::Optional) { + if (appendSpace) OS << ' '; + OS << "_Optional"; + appendSpace = true; + } } void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) { diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -942,6 +942,11 @@ Q.removeRestrict(); return llvm::dwarf::DW_TAG_restrict_type; } + if (Q.hasOptional()) { + Q.removeOptional(); + return llvm::dwarf::DW_TAG_LLVM_optional_type; + } + return (llvm::dwarf::Tag)0; } @@ -1698,6 +1703,7 @@ Qc.removeConst(); Qc.removeVolatile(); Qc.removeRestrict(); + Qc.removeOptional(); Qc.removeUnaligned(); // Keep the removed qualifiers in sync with // CreateQualifiedType(const FunctionPrototype*, DIFile *Unit) diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -600,7 +600,7 @@ } bool canBePointerOrReferenceQualifier() const { - return isOneOf(tok::kw_const, tok::kw_restrict, tok::kw_volatile, + return isOneOf(tok::kw_const, tok::kw_restrict, tok::kw_volatile, tok::kw__Optional, tok::kw___attribute, tok::kw__Nonnull, tok::kw__Nullable, tok::kw__Null_unspecified, tok::kw___ptr32, tok::kw___ptr64, TT_AttributeMacro); @@ -762,7 +762,7 @@ const FormatToken *T = this; do { T = T->getPreviousNonComment(); - } while (T && T->isOneOf(tok::kw_const, tok::kw_volatile, tok::amp, + } while (T && T->isOneOf(tok::kw_const, tok::kw_volatile, tok::kw__Optional, tok::amp, tok::ampamp)); return T && T->is(tok::kw_auto); } diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp --- a/clang/lib/Format/QualifierAlignmentFixer.cpp +++ b/clang/lib/Format/QualifierAlignmentFixer.cpp @@ -410,6 +410,7 @@ .Case("type", tok::kw_typeof) .Case("const", tok::kw_const) .Case("volatile", tok::kw_volatile) + .Case("_Optional", tok::kw__Optional) .Case("static", tok::kw_static) .Case("inline", tok::kw_inline) .Case("constexpr", tok::kw_constexpr) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2199,7 +2199,7 @@ // Functions which end with decorations like volatile, noexcept are unlikely // to be casts. - if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const, + if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw__Optional, tok::kw_const, tok::kw_requires, tok::kw_throw, tok::arrow, Keywords.kw_override, Keywords.kw_final) || isCpp11AttributeSpecifier(*Tok.Next)) { @@ -3615,7 +3615,7 @@ if (Previous) { if (Previous->endsSequence(tok::kw_operator)) return Style.PointerAlignment != FormatStyle::PAS_Left; - if (Previous->is(tok::kw_const) || Previous->is(tok::kw_volatile)) { + if (Previous->is(tok::kw_const) || Previous->is(tok::kw_volatile) || Previous->is(tok::kw__Optional)) { return (Style.PointerAlignment != FormatStyle::PAS_Left) || (Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_After) || @@ -3803,7 +3803,7 @@ } if (Right.getType() == TT_TrailingAnnotation && Right.isOneOf(tok::amp, tok::ampamp) && - Left.isOneOf(tok::kw_const, tok::kw_volatile) && + Left.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw__Optional) && (!Right.Next || Right.Next->is(tok::semi))) { // Match const and volatile ref-qualifiers without any additional // qualifiers such as diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -3391,6 +3391,7 @@ for (; Lookahead < 50; PeekNext()) { switch (NextToken->Tok.getKind()) { case tok::kw_volatile: + case tok::kw__Optional: case tok::kw_const: case tok::comma: FormatTok = Tokens->setPosition(StoredPosition); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -857,6 +857,7 @@ switch (Tok.getKind()) { case tok::kw_const: case tok::kw_volatile: + case tok::kw__Optional: case tok::kw___fastcall: case tok::kw___stdcall: case tok::kw___thiscall: @@ -4244,6 +4245,10 @@ isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, getLangOpts()); break; + case tok::kw__Optional: + isInvalid = DS.SetTypeQual(DeclSpec::TQ_optional, Loc, PrevSpec, DiagID, + getLangOpts()); + break; case tok::kw_restrict: isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, getLangOpts()); @@ -5329,6 +5334,7 @@ // type-qualifier case tok::kw_const: case tok::kw_volatile: + case tok::kw__Optional: case tok::kw_restrict: case tok::kw__Sat: @@ -5526,6 +5532,7 @@ // type-qualifier case tok::kw_const: case tok::kw_volatile: + case tok::kw__Optional: case tok::kw_restrict: case tok::kw__Sat: @@ -5832,6 +5839,10 @@ isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, getLangOpts()); break; + case tok::kw__Optional: + isInvalid = DS.SetTypeQual(DeclSpec::TQ_optional, Loc, PrevSpec, DiagID, + getLangOpts()); + break; case tok::kw_restrict: isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, getLangOpts()); @@ -6123,8 +6134,9 @@ // Remember that we parsed a pointer type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getPointer( DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(), - DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(), - DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()), + DS.getVolatileSpecLoc(), DS.getOptionalSpecLoc(), + DS.getRestrictSpecLoc(), DS.getAtomicSpecLoc(), + DS.getUnalignedSpecLoc()), std::move(DS.getAttributes()), SourceLocation()); else // Remember that we parsed a Block type, and remember the type-quals. @@ -6156,6 +6168,9 @@ if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) Diag(DS.getVolatileSpecLoc(), diag::err_invalid_reference_qualifier_application) << "volatile"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_optional) + Diag(DS.getOptionalSpecLoc(), + diag::err_invalid_reference_qualifier_application) << "_Optional"; // 'restrict' is permitted as an extension. if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) Diag(DS.getAtomicSpecLoc(), diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1434,6 +1434,7 @@ // Type qualifiers case tok::kw_const: // struct foo {...} const x; case tok::kw_volatile: // struct foo {...} volatile x; + case tok::kw__Optional: // struct foo {...} _Optional x; case tok::kw_restrict: // struct foo {...} restrict x; case tok::kw__Atomic: // struct foo {...} _Atomic x; case tok::kw___unaligned: // struct foo {...} __unaligned *x; diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -1137,6 +1137,7 @@ case tok::kw_virtual: case tok::kw_void: case tok::kw_volatile: + case tok::kw__Optional: case tok::kw_wchar_t: case tok::kw_while: case tok::kw__Bool: diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -885,7 +885,7 @@ if (!TrySkipAttributes()) return TPResult::Error; - while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict, + while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw__Optional, tok::kw_restrict, tok::kw__Nonnull, tok::kw__Nullable, tok::kw__Nullable_result, tok::kw__Null_unspecified, tok::kw__Atomic)) @@ -1460,6 +1460,7 @@ // cv-qualifier case tok::kw_const: case tok::kw_volatile: + case tok::kw__Optional: return TPResult::True; // OpenCL address space qualifiers @@ -1919,7 +1920,7 @@ TPR = TPResult::False; else { const Token &Next = NextToken(); - if (Next.isOneOf(tok::amp, tok::ampamp, tok::kw_const, tok::kw_volatile, + if (Next.isOneOf(tok::amp, tok::ampamp, tok::kw_const, tok::kw_volatile, tok::kw__Optional, tok::kw_throw, tok::kw_noexcept, tok::l_square, tok::l_brace, tok::kw_try, tok::equal, tok::arrow) || isCXX11VirtSpecifier(Next)) @@ -2091,7 +2092,7 @@ return TPResult::Error; // cv-qualifier-seq - while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw___unaligned, + while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw__Optional, tok::kw___unaligned, tok::kw_restrict)) ConsumeToken(); diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -431,6 +431,8 @@ Handle(TQ_const, "const", TQ_constLoc); if (TypeQualifiers & TQ_volatile) Handle(TQ_volatile, "volatile", TQ_volatileLoc); + if (TypeQualifiers & TQ_optional) + Handle(TQ_optional, "_Optional", TQ_optionalLoc); if (TypeQualifiers & TQ_restrict) Handle(TQ_restrict, "restrict", TQ_restrictLoc); if (TypeQualifiers & TQ_unaligned) @@ -617,6 +619,7 @@ case DeclSpec::TQ_const: return "const"; case DeclSpec::TQ_restrict: return "restrict"; case DeclSpec::TQ_volatile: return "volatile"; + case DeclSpec::TQ_optional: return "_Optional"; case DeclSpec::TQ_atomic: return "_Atomic"; case DeclSpec::TQ_unaligned: return "__unaligned"; } @@ -985,6 +988,7 @@ case TQ_const: TQ_constLoc = Loc; return false; case TQ_restrict: TQ_restrictLoc = Loc; return false; case TQ_volatile: TQ_volatileLoc = Loc; return false; + case TQ_optional: TQ_optionalLoc = Loc; return false; case TQ_unaligned: TQ_unalignedLoc = Loc; return false; case TQ_atomic: TQ_atomicLoc = Loc; return false; } @@ -1135,11 +1139,12 @@ getTypeSpecSign() != TypeSpecifierSign::Unspecified || TypeAltiVecVector || TypeAltiVecPixel || TypeAltiVecBool || TypeQualifiers)) { - const unsigned NumLocs = 9; + const unsigned NumLocs = 10; SourceLocation ExtraLocs[NumLocs] = { TSWRange.getBegin(), TSCLoc, TSSLoc, AltiVecLoc, TQ_constLoc, TQ_restrictLoc, - TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc}; + TQ_volatileLoc, TQ_optionalLoc, TQ_atomicLoc, + TQ_unalignedLoc}; FixItHint Hints[NumLocs]; SourceLocation FirstLoc; for (unsigned I = 0; I != NumLocs; ++I) { diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5849,6 +5849,8 @@ Results.AddResult("const"); if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile)) Results.AddResult("volatile"); + if (!(DS.getTypeQualifiers() & DeclSpec::TQ_optional)) + Results.AddResult("_Optional"); if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) Results.AddResult("restrict"); if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic)) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5281,6 +5281,8 @@ Diag(DS.getConstSpecLoc(), DiagID) << "const"; if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) Diag(DS.getConstSpecLoc(), DiagID) << "volatile"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_optional) + Diag(DS.getConstSpecLoc(), DiagID) << "_Optional"; // Restrict is covered above. if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) Diag(DS.getAtomicSpecLoc(), DiagID) << "_Atomic"; @@ -5537,6 +5539,11 @@ diag::ext_anonymous_struct_union_qualified) << Record->isUnion() << "volatile" << FixItHint::CreateRemoval(DS.getVolatileSpecLoc()); + if (DS.getTypeQualifiers() & DeclSpec::TQ_optional) + Diag(DS.getOptionalSpecLoc(), + diag::ext_anonymous_struct_union_qualified) + << Record->isUnion() << "_Optional" + << FixItHint::CreateRemoval(DS.getOptionalSpecLoc()); if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) Diag(DS.getRestrictSpecLoc(), diag::ext_anonymous_struct_union_qualified) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -10566,7 +10566,7 @@ diagnoseIgnoredQualifiers( diag::err_constructor_return_type, TypeQuals, SourceLocation(), D.getDeclSpec().getConstSpecLoc(), D.getDeclSpec().getVolatileSpecLoc(), - D.getDeclSpec().getRestrictSpecLoc(), + D.getDeclSpec().getOptionalSpecLoc(), D.getDeclSpec().getRestrictSpecLoc(), D.getDeclSpec().getAtomicSpecLoc()); D.setInvalidType(); } @@ -10742,6 +10742,7 @@ SourceLocation(), D.getDeclSpec().getConstSpecLoc(), D.getDeclSpec().getVolatileSpecLoc(), + D.getDeclSpec().getOptionalSpecLoc(), D.getDeclSpec().getRestrictSpecLoc(), D.getDeclSpec().getAtomicSpecLoc()); D.setInvalidType(); @@ -17082,6 +17083,8 @@ Diag(DS.getConstSpecLoc(), diag::err_friend_decl_spec) << "const"; if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) Diag(DS.getVolatileSpecLoc(), diag::err_friend_decl_spec) << "volatile"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_optional) + Diag(DS.getOptionalSpecLoc(), diag::err_friend_decl_spec) << "_Optional"; if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) Diag(DS.getRestrictSpecLoc(), diag::err_friend_decl_spec) << "restrict"; if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -1613,6 +1613,7 @@ SourceLocation(), SourceLocation(), SourceLocation(), + SourceLocation(), SourceLocation()), starLoc); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1366,9 +1366,11 @@ if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() && !isa(NewMethod)) NewQuals.addConst(); - // We do not allow overloading based off of '__restrict'. + // We do not allow overloading based off of '__restrict' or '_Optional'. OldQuals.removeRestrict(); + OldQuals.removeOptional(); NewQuals.removeRestrict(); + NewQuals.removeOptional(); if (OldQuals != NewQuals) return true; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -781,6 +781,7 @@ for (QualLoc Qual : {QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()), QualLoc(DeclSpec::TQ_restrict, DS.getRestrictSpecLoc()), QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()), + QualLoc(DeclSpec::TQ_optional, DS.getOptionalSpecLoc()), QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())}) { if (!(RemoveTQs & Qual.first)) continue; @@ -1878,7 +1879,7 @@ if (TypeQuals && Result->isReferenceType()) { diagnoseAndRemoveTypeQualifiers( S, DS, TypeQuals, Result, - DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic, + DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_optional | DeclSpec::TQ_atomic, diag::warn_typecheck_reference_qualifiers); } @@ -1897,7 +1898,7 @@ << "volatile"; } - // C90 doesn't have restrict nor _Atomic, so it doesn't force us to + // C90 doesn't have restrict, nor _Optional, nor _Atomic, so it doesn't force us to // produce a warning in this case. } @@ -1987,7 +1988,7 @@ // Ignore any attempt to form a cv-qualified reference. if (T->isReferenceType()) CVRAU &= - ~(DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic); + ~(DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_optional | DeclSpec::TQ_atomic); // Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic and // TQ_unaligned; @@ -3230,6 +3231,7 @@ SourceLocation FallbackLoc, SourceLocation ConstQualLoc, SourceLocation VolatileQualLoc, + SourceLocation OptionalQualLoc, SourceLocation RestrictQualLoc, SourceLocation AtomicQualLoc, SourceLocation UnalignedQualLoc) { @@ -3240,9 +3242,10 @@ const char *Name; unsigned Mask; SourceLocation Loc; - } const QualKinds[5] = { + } const QualKinds[6] = { { "const", DeclSpec::TQ_const, ConstQualLoc }, { "volatile", DeclSpec::TQ_volatile, VolatileQualLoc }, + { "_Optional", DeclSpec::TQ_optional, OptionalQualLoc }, { "restrict", DeclSpec::TQ_restrict, RestrictQualLoc }, { "__unaligned", DeclSpec::TQ_unaligned, UnalignedQualLoc }, { "_Atomic", DeclSpec::TQ_atomic, AtomicQualLoc } @@ -3251,7 +3254,7 @@ SmallString<32> QualStr; unsigned NumQuals = 0; SourceLocation Loc; - FixItHint FixIts[5]; + FixItHint FixIts[6]; // Build a string naming the redundant qualifiers. for (auto &E : QualKinds) { @@ -3273,7 +3276,7 @@ } Diag(Loc.isInvalid() ? FallbackLoc : Loc, DiagID) - << QualStr << NumQuals << FixIts[0] << FixIts[1] << FixIts[2] << FixIts[3]; + << QualStr << NumQuals << FixIts[0] << FixIts[1] << FixIts[2] << FixIts[3] << FixIts[4]; } // Diagnose pointless type qualifiers on the return type of a function. @@ -3305,6 +3308,7 @@ SourceLocation(), PTI.ConstQualLoc, PTI.VolatileQualLoc, + PTI.OptionalQualLoc, PTI.RestrictQualLoc, PTI.AtomicQualLoc, PTI.UnalignedQualLoc); @@ -3342,6 +3346,7 @@ D.getIdentifierLoc(), D.getDeclSpec().getConstSpecLoc(), D.getDeclSpec().getVolatileSpecLoc(), + D.getDeclSpec().getOptionalSpecLoc(), D.getDeclSpec().getRestrictSpecLoc(), D.getDeclSpec().getAtomicSpecLoc(), D.getDeclSpec().getUnalignedSpecLoc()); diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -93,6 +93,9 @@ eEncodingIsAtomicUID, /// This type is the synthetic type whose UID is m_encoding_uid. eEncodingIsSyntheticUID + /// This type is the type whose UID is m_encoding_uid with the _Optional + /// qualifier added. + eEncodingIsOptionalUID, }; enum class ResolveState : unsigned char { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -469,6 +469,7 @@ case DW_TAG_rvalue_reference_type: case DW_TAG_const_type: case DW_TAG_restrict_type: + case DW_TAG_optional_type: case DW_TAG_volatile_type: case DW_TAG_atomic_type: case DW_TAG_unspecified_type: { @@ -621,6 +622,9 @@ case DW_TAG_restrict_type: encoding_data_type = Type::eEncodingIsRestrictUID; break; + case DW_TAG_optional_type: + encoding_data_type = Type::eEncodingIsOptionalUID; + break; case DW_TAG_volatile_type: encoding_data_type = Type::eEncodingIsVolatileUID; break; @@ -3113,6 +3117,8 @@ type_quals |= clang::Qualifiers::Const; if (encoding_mask & (1u << Type::eEncodingIsVolatileUID)) type_quals |= clang::Qualifiers::Volatile; + if (encoding_mask & (1u << Type::eEncodingIsOptionalUID)) + type_quals |= clang::Qualifiers::Optional; } } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -308,6 +308,9 @@ case DW_TAG_volatile_type: s.PutCString("volatile "); break; + case DW_TAG_optional_type: + s.PutCString("_Optional "); + break; case DW_TAG_LLVM_ptrauth_type: { unsigned key = GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_key, 0); bool isAddressDiscriminated = GetAttributeValueAsUnsigned( diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -581,6 +581,9 @@ if ((pointer.getOptions() & PointerOptions::Restrict) != PointerOptions::None) pointer_type.addRestrict(); + if ((pointer.getOptions() & PointerOptions::Optional) != PointerOptions::None) + pointer_type.addOptional(); + return pointer_type; } diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp --- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -464,6 +464,9 @@ if (udt->isVolatileType()) clang_type = clang_type.AddVolatileModifier(); + if (udt->isOptionalType()) + clang_type = clang_type.AddOptionalModifier(); + GetDeclarationForSymbol(type, decl); return m_ast.GetSymbolFile()->MakeType( type.getSymIndexId(), ConstString(name), udt->getLength(), nullptr, @@ -533,6 +536,9 @@ if (enum_type->isVolatileType()) ast_enum = ast_enum.AddVolatileModifier(); + if (enum_type->isOptionalType()) + ast_enum = ast_enum.AddOptionalModifier(); + GetDeclarationForSymbol(type, decl); return m_ast.GetSymbolFile()->MakeType( type.getSymIndexId(), ConstString(name), bytes, nullptr, @@ -579,6 +585,9 @@ if (type_def->isVolatileType()) ast_typedef = ast_typedef.AddVolatileModifier(); + if (type_def->isOptionalType()) + ast_typedef = ast_typedef.AddOptionalModifier(); + GetDeclarationForSymbol(type, decl); std::optional size; if (type_def->getLength()) @@ -654,6 +663,8 @@ type_quals |= clang::Qualifiers::Const; if (func_sig->isVolatileType()) type_quals |= clang::Qualifiers::Volatile; + if (func_sig->isOptionalType()) + type_quals |= clang::Qualifiers::Optional; auto cc = TranslateCallingConvention(func_sig->getCallingConvention()); CompilerType func_sig_ast_type = m_ast.CreateFunctionType(return_ast_type, arg_list.data(), @@ -724,6 +735,9 @@ if (builtin_type->isVolatileType()) builtin_ast_type = builtin_ast_type.AddVolatileModifier(); + if (builtin_type->isOptionalType()) + builtin_ast_type = builtin_ast_type.AddOptionalModifier(); + auto type_name = GetPDBBuiltinTypeName(*builtin_type, builtin_ast_type); return m_ast.GetSymbolFile()->MakeType( @@ -781,6 +795,9 @@ if (pointer_type->isRestrictedType()) pointer_ast_type = pointer_ast_type.AddRestrictModifier(); + if (pointer_type->isOptionalType()) + pointer_ast_type = pointer_ast_type.AddOptionalModifier(); + return m_ast.GetSymbolFile()->MakeType( pointer_type->getSymIndexId(), ConstString(), pointer_type->getLength(), nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -230,6 +230,9 @@ case eEncodingIsSyntheticUID: s->PutCString(" (synthetic type)"); break; + case eEncodingIsOptionalUID: + s->PutCString(" (unresolved _Optional type)"); + break; } } } @@ -291,6 +294,9 @@ case eEncodingIsSyntheticUID: s->PutCString(" (synthetic type)"); break; + case eEncodingIsOptionalUID: + s->PutCString(" (unresolved _Optional type)"); + break; } } @@ -354,6 +360,7 @@ case eEncodingIsConstUID: case eEncodingIsRestrictUID: case eEncodingIsVolatileUID: + case eEncodingIsOptionalUID: case eEncodingIsAtomicUID: case eEncodingIsTypedefUID: { Type *encoding_type = GetEncodingType(); @@ -511,6 +518,11 @@ encoding_type->GetForwardCompilerType().AddVolatileModifier(); break; + case eEncodingIsOptionalUID: + m_compiler_type = + encoding_type->GetForwardCompilerType().AddOptionalModifier(); + break; + case eEncodingIsAtomicUID: m_compiler_type = encoding_type->GetForwardCompilerType().GetAtomicType(); @@ -570,6 +582,10 @@ m_compiler_type = void_compiler_type.AddVolatileModifier(); break; + case eEncodingIsOptionalUID: + m_compiler_type = void_compiler_type.AddOptionalModifier(); + break; + case eEncodingIsAtomicUID: m_compiler_type = void_compiler_type.GetAtomicType(); break; diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -5567,8 +5567,9 @@ ``DW_TAG_typedef`` is used to provide a name for the ``baseType:``. ``DW_TAG_pointer_type``, ``DW_TAG_reference_type``, ``DW_TAG_const_type``, -``DW_TAG_volatile_type``, ``DW_TAG_restrict_type``, ``DW_TAG_atomic_type`` and -``DW_TAG_immutable_type`` are used to qualify the ``baseType:``. +``DW_TAG_volatile_type``, ``DW_TAG_restrict_type``, ``DW_TAG_LLVM_optional_type``, +``DW_TAG_atomic_type`` and ``DW_TAG_immutable_type`` are used to qualify the +``baseType:``. Note that the ``void *`` type is expressed as a type derived from NULL. diff --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst --- a/llvm/docs/SourceLevelDebugging.rst +++ b/llvm/docs/SourceLevelDebugging.rst @@ -1945,6 +1945,7 @@ * DW_TAG_packed_type * DW_TAG_volatile_type * DW_TAG_restrict_type +* DW_TAG_LLVM_optional_type * DW_TAG_atomic_type * DW_TAG_interface_type * DW_TAG_unspecified_type diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -208,6 +208,7 @@ HANDLE_DW_TAG(0x0049, call_site_parameter, 5, DWARF, DW_KIND_NONE) HANDLE_DW_TAG(0x004a, skeleton_unit, 5, DWARF, DW_KIND_NONE) HANDLE_DW_TAG(0x004b, immutable_type, 5, DWARF, DW_KIND_TYPE) + // Vendor extensions: HANDLE_DW_TAG(0x4081, MIPS_loop, 0, MIPS, DW_KIND_NONE) // Conflicting: @@ -253,6 +254,8 @@ // LLVM HANDLE_DW_TAG(0x6000, LLVM_annotation, 0, LLVM, DW_KIND_NONE) +HANDLE_DW_TAG(0x6001, LLVM_optional_type, 0, LLVM, DW_KIND_TYPE) + // Green Hills. HANDLE_DW_TAG(0x8004, GHS_namespace, 0, GHS, DW_KIND_NONE) diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/llvm/include/llvm/DebugInfo/CodeView/CodeView.h --- a/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -302,7 +302,8 @@ None = 0x0000, Const = 0x0001, Volatile = 0x0002, - Unaligned = 0x0004 + Unaligned = 0x0004, + Optional = 0x0008 }; CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ModifierOptions) @@ -366,6 +367,7 @@ Const = 0x00000400, Unaligned = 0x00000800, Restrict = 0x00001000, + Optional = 0x00002000, WinRTSmartPointer = 0x00080000, LValueRefThisPointer = 0x00100000, RValueRefThisPointer = 0x00200000 diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h --- a/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -337,6 +337,10 @@ return !!(Attrs & uint32_t(PointerOptions::Restrict)); } + bool isOptional() const { + return !!(Attrs & uint32_t(PointerOptions::Optional)); + } + bool isLValueReferenceThisPtr() const { return !!(Attrs & uint32_t(PointerOptions::LValueRefThisPointer)); } diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h @@ -48,7 +48,7 @@ DWARFDie appendQualifiedNameBefore(DWARFDie D); bool appendTemplateParameters(DWARFDie D, bool *FirstParameter = nullptr); void decomposeConstVolatile(DWARFDie &N, DWARFDie &T, DWARFDie &C, - DWARFDie &V); + DWARFDie &V, DWARFDie &O); void appendConstVolatileQualifierAfter(DWARFDie N); void appendConstVolatileQualifierBefore(DWARFDie N); @@ -58,7 +58,7 @@ void appendSubroutineNameAfter(DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial, bool Const, - bool Volatile); + bool Volatile, bool Optional); void appendScopes(DWARFDie D); }; diff --git a/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h --- a/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h +++ b/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h @@ -220,6 +220,7 @@ bool isVirtualBaseClass() const override; bool isVirtualInheritance() const override; bool isVolatileType() const override; + bool isOptionalType() const override; bool wasInlined() const override; std::string getUnused() const override; diff --git a/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h --- a/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h +++ b/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h @@ -247,6 +247,7 @@ virtual bool isVirtualBaseClass() const = 0; virtual bool isVirtualInheritance() const = 0; virtual bool isVolatileType() const = 0; + virtual bool isOptionalType() const = 0; virtual bool wasInlined() const = 0; virtual std::string getUnused() const = 0; }; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h @@ -225,6 +225,7 @@ bool isVirtualBaseClass() const override; bool isVirtualInheritance() const override; bool isVolatileType() const override; + bool isOptionalType() const override; bool wasInlined() const override; std::string getUnused() const override; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h @@ -40,6 +40,7 @@ PDB_LocType getLocationType() const override; bool isConstType() const override; bool isVolatileType() const override; + bool isOptionalType() const override; bool isUnalignedType() const override; Variant getValue() const override; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h @@ -33,6 +33,7 @@ bool isConstType() const override; bool isUnalignedType() const override; bool isVolatileType() const override; + bool isOptionalType() const override; uint32_t getCount() const override; SymIndexId getTypeId() const override; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h @@ -35,6 +35,7 @@ uint64_t getLength() const override; bool isUnalignedType() const override; bool isVolatileType() const override; + bool isOptionalType() const override; protected: NativeSession &Session; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h @@ -47,6 +47,7 @@ std::string getName() const override; bool isConstType() const override; bool isVolatileType() const override; + bool isOptionalType() const override; bool isUnalignedType() const override; bool isNested() const override; bool hasOverloadedOperator() const override; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h @@ -49,6 +49,7 @@ bool isCxxReturnUdt() const override; bool isUnalignedType() const override; bool isVolatileType() const override; + bool isOptionalType() const override; private: void initializeArgList(codeview::TypeIndex ArgListTI); diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h @@ -42,6 +42,7 @@ SymIndexId getTypeId() const override; bool isRestrictedType() const override; bool isVolatileType() const override; + bool isOptionalType() const override; bool isUnalignedType() const override; bool isSingleInheritance() const override; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h @@ -59,6 +59,7 @@ bool isValueUdt() const override; bool isUnalignedType() const override; bool isVolatileType() const override; + bool isOptionalType() const override; protected: codeview::TypeIndex Index; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h @@ -32,6 +32,7 @@ bool isConstType() const override; bool isVolatileType() const override; + bool isOptionalType() const override; bool isUnalignedType() const override; uint32_t getCount() const override; diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h @@ -49,6 +49,7 @@ FORWARD_SYMBOL_METHOD(getValue) FORWARD_SYMBOL_METHOD(getVirtualAddress) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) std::unique_ptr getLineNumbers() const; uint32_t getCompilandId() const; diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -77,6 +77,7 @@ FORWARD_SYMBOL_METHOD(getVirtualAddress) FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) std::unique_ptr getLineNumbers() const; uint32_t getCompilandId() const; diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h @@ -44,6 +44,7 @@ FORWARD_SYMBOL_METHOD(getVirtualAddress) FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } // namespace pdb } // namespace llvm diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h @@ -31,6 +31,7 @@ FORWARD_SYMBOL_ID_METHOD_WITH_NAME(getType, getElementType) FORWARD_SYMBOL_METHOD(isUnalignedType) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } // namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h @@ -51,6 +51,7 @@ // FORWARD_SYMBOL_METHOD(getVirtualBaseTableType) FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } // namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h @@ -27,6 +27,7 @@ FORWARD_SYMBOL_ID_METHOD(getLexicalParent) FORWARD_SYMBOL_METHOD(isUnalignedType) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } // namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h @@ -46,6 +46,7 @@ getUnderlyingType) FORWARD_SYMBOL_METHOD(isUnalignedType) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } // namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -39,6 +39,7 @@ FORWARD_SYMBOL_ID_METHOD_WITH_NAME(getType, getReturnType) FORWARD_SYMBOL_METHOD(isUnalignedType) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } // namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h @@ -34,6 +34,7 @@ FORWARD_SYMBOL_METHOD(isRestrictedType) FORWARD_SYMBOL_METHOD(isUnalignedType) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } // namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h @@ -41,6 +41,7 @@ FORWARD_SYMBOL_METHOD(isUnalignedType) FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } // namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h @@ -45,6 +45,7 @@ FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape) FORWARD_SYMBOL_METHOD(isVolatileType) FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } } // namespace llvm diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h @@ -28,6 +28,7 @@ FORWARD_SYMBOL_ID_METHOD(getType) FORWARD_SYMBOL_METHOD(isUnalignedType) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } // namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h @@ -26,6 +26,7 @@ FORWARD_SYMBOL_ID_METHOD(getLexicalParent) FORWARD_SYMBOL_METHOD(isUnalignedType) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(isOptionalType) }; } // namespace pdb diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1648,6 +1648,7 @@ case dwarf::DW_TAG_restrict_type: case dwarf::DW_TAG_const_type: case dwarf::DW_TAG_volatile_type: + case dwarf::DW_TAG_LLVM_optional_type: // TODO: add support for DW_TAG_atomic_type here return lowerTypeModifier(cast(Ty)); case dwarf::DW_TAG_subroutine_type: @@ -1990,6 +1991,10 @@ Mods |= ModifierOptions::Volatile; PO |= PointerOptions::Volatile; break; + case dwarf::DW_TAG_LLVM_optional_type: + Mods |= ModifierOptions::Optional; + PO |= PointerOptions::Optional; + break; case dwarf::DW_TAG_restrict_type: // Only pointer types be marked with __restrict. There is no known flag // for __restrict in LF_MODIFIER records. @@ -2334,6 +2339,7 @@ switch (Ty->getTag()) { case dwarf::DW_TAG_const_type: case dwarf::DW_TAG_volatile_type: + case dwarf::DW_TAG_LLVM_optional_type: // FIXME: we should apply the qualifier types to the indirect fields // rather than dropping them. Ty = cast(Ty)->getBaseType(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -154,7 +154,7 @@ if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type && - Tag != dwarf::DW_TAG_immutable_type) + Tag != dwarf::DW_TAG_immutable_type && Tag != dwarf::DW_TAG_LLVM_optional_type) return DDTy->getSizeInBits(); DIType *BaseType = DDTy->getBaseType(); @@ -210,7 +210,7 @@ assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type || T == dwarf::DW_TAG_volatile_type || T == dwarf::DW_TAG_restrict_type || T == dwarf::DW_TAG_atomic_type || - T == dwarf::DW_TAG_immutable_type); + T == dwarf::DW_TAG_immutable_type || T == dwarf::DW_TAG_LLVM_optional_type); assert(DTy->getBaseType() && "Expected valid base type"); return isUnsignedDIType(DTy->getBaseType()); } diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -122,6 +122,7 @@ case dwarf::DW_TAG_packed_type: case dwarf::DW_TAG_volatile_type: case dwarf::DW_TAG_restrict_type: + case dwarf::DW_TAG_LLVM_optional_type: case dwarf::DW_TAG_atomic_type: case dwarf::DW_TAG_interface_type: case dwarf::DW_TAG_unspecified_type: diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -507,6 +507,7 @@ case DW_TAG_immutable_type: case DW_TAG_volatile_type: case DW_TAG_restrict_type: + case DW_TAG_LLVM_optional_type: case DW_TAG_typedef: { if (DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type)) return BaseType.getTypeSize(PointerSize); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp @@ -71,7 +71,8 @@ } DWARFDie DWARFTypePrinter::skipQualifiers(DWARFDie D) { while (D && (D.getTag() == DW_TAG_const_type || - D.getTag() == DW_TAG_volatile_type)) + D.getTag() == DW_TAG_volatile_type || + D.getTag() == DW_TAG_LLVM_optional_type)) D = resolveReferencedType(D); return D; } @@ -148,6 +149,7 @@ break; case DW_TAG_const_type: case DW_TAG_volatile_type: + case DW_TAG_LLVM_optional_type: appendConstVolatileQualifierBefore(D); break; case DW_TAG_namespace: { @@ -219,7 +221,7 @@ switch (D.getTag()) { case DW_TAG_subroutine_type: { appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false, - false); + false, false); break; } case DW_TAG_array_type: { @@ -228,6 +230,7 @@ } case DW_TAG_const_type: case DW_TAG_volatile_type: + case DW_TAG_LLVM_optional_type: appendConstVolatileQualifierAfter(D); break; case DW_TAG_ptr_to_member_type: @@ -456,36 +459,55 @@ return IsTemplate; } void DWARFTypePrinter::decomposeConstVolatile(DWARFDie &N, DWARFDie &T, - DWARFDie &C, DWARFDie &V) { + DWARFDie &C, DWARFDie &V, DWARFDie &O) { + switch (N.getTag()) { + case DW_TAG_const_type: + C = N; + break; + case DW_TAG_volatile_type: + V = N; + break; + case DW_TAG_LLVM_optional_type: + O = N; + break; + } (N.getTag() == DW_TAG_const_type ? C : V) = N; T = resolveReferencedType(N); if (T) { - auto Tag = T.getTag(); - if (Tag == DW_TAG_const_type) { + switch (T.getTag()) { + case DW_TAG_const_type: C = T; T = resolveReferencedType(T); - } else if (Tag == DW_TAG_volatile_type) { + break; + case DW_TAG_volatile_type: V = T; T = resolveReferencedType(T); + break; + case DW_TAG_LLVM_optional_type: + O = T; + T = resolveReferencedType(T); + break; } } } void DWARFTypePrinter::appendConstVolatileQualifierAfter(DWARFDie N) { DWARFDie C; DWARFDie V; + DWARFDie O; DWARFDie T; - decomposeConstVolatile(N, T, C, V); + decomposeConstVolatile(N, T, C, V, O); if (T && T.getTag() == DW_TAG_subroutine_type) appendSubroutineNameAfter(T, resolveReferencedType(T), false, C.isValid(), - V.isValid()); + V.isValid(), O.isValid()); else appendUnqualifiedNameAfter(T, resolveReferencedType(T)); } void DWARFTypePrinter::appendConstVolatileQualifierBefore(DWARFDie N) { DWARFDie C; DWARFDie V; + DWARFDie O; DWARFDie T; - decomposeConstVolatile(N, T, C, V); + decomposeConstVolatile(N, T, C, V, O); bool Subroutine = T && T.getTag() == DW_TAG_subroutine_type; DWARFDie A = T; while (A && A.getTag() == DW_TAG_array_type) @@ -499,6 +521,8 @@ OS << "const "; if (V) OS << "volatile "; + if (O) + OS << "_Optional "; } appendQualifiedNameBefore(T); if (!Leading && !Subroutine) { @@ -510,6 +534,11 @@ OS << ' '; OS << "volatile"; } + if (O) { + if (C || V) + OS << ' '; + OS << "_Optional"; + } } } void DWARFTypePrinter::appendUnqualifiedName(DWARFDie D, @@ -521,7 +550,7 @@ } void DWARFTypePrinter::appendSubroutineNameAfter( DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial, bool Const, - bool Volatile) { + bool Volatile, bool Optional) { DWARFDie FirstParamIfArtificial; OS << '('; EndedWithTemplate = false; @@ -555,6 +584,7 @@ if (DWARFDie U = resolveReferencedType(CV)) { Const |= U.getTag() == DW_TAG_const_type; Volatile |= U.getTag() == DW_TAG_volatile_type; + Optional |= U.getTag() == DW_TAG_LLVM_optional_type; return U; } return DWARFDie(); @@ -627,6 +657,8 @@ OS << " const"; if (Volatile) OS << " volatile"; + if (Optional) + OS << " _Optional"; if (D.find(DW_AT_reference)) OS << " &"; if (D.find(DW_AT_rvalue_reference)) diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp --- a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp @@ -1261,6 +1261,10 @@ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_volatileType); } +bool DIARawSymbol::isOptionalType() const { + return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_optionalType); +} + bool DIARawSymbol::wasInlined() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_wasInlined); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -724,6 +724,10 @@ return false; } +bool NativeRawSymbol::isOptionalType() const { + return false; +} + bool NativeRawSymbol::wasInlined() const { return false; } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp @@ -42,6 +42,7 @@ dumpSymbolField(OS, "constType", isConstType(), Indent); dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); + dumpSymbolField(OS, "optionalType", isOptionalType(), Indent); dumpSymbolField(OS, "value", getValue(), Indent); } @@ -71,6 +72,8 @@ bool NativeSymbolEnumerator::isVolatileType() const { return false; } +bool NativeSymbolEnumerator::isOptionalType() const { return false; } + bool NativeSymbolEnumerator::isUnalignedType() const { return false; } Variant NativeSymbolEnumerator::getValue() const { diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp @@ -41,6 +41,7 @@ dumpSymbolField(OS, "constType", isConstType(), Indent); dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); + dumpSymbolField(OS, "optionalType", isOptionalType(), Indent); } SymIndexId NativeTypeArray::getArrayIndexTypeId() const { @@ -53,6 +54,8 @@ bool NativeTypeArray::isVolatileType() const { return false; } +bool NativeTypeArray::isOptionalType() const { return false; } + uint32_t NativeTypeArray::getCount() const { NativeRawSymbol &Element = Session.getSymbolCache().getNativeSymbolById(getTypeId()); diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp @@ -43,3 +43,7 @@ bool NativeTypeBuiltin::isVolatileType() const { return (Mods & ModifierOptions::Volatile) != ModifierOptions::None; } + +bool NativeTypeBuiltin::isOptionalType() const { + return (Mods & ModifierOptions::Optional) != ModifierOptions::None; +} diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp @@ -161,6 +161,7 @@ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent); dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); + dumpSymbolField(OS, "optionalType", isOptionalType(), Indent); } std::unique_ptr @@ -370,6 +371,13 @@ ModifierOptions::None); } +bool NativeTypeEnum::isOptionalType() const { + if (!Modifiers) + return false; + return ((Modifiers->getModifiers() & ModifierOptions::Optional) != + ModifierOptions::None); +} + bool NativeTypeEnum::isUnalignedType() const { if (!Modifiers) return false; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp @@ -129,6 +129,7 @@ dumpSymbolField(OS, "isCxxReturnUdt", isCxxReturnUdt(), Indent); dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); + dumpSymbolField(OS, "optionalType", isOptionalType(), Indent); } std::unique_ptr @@ -198,3 +199,5 @@ bool NativeTypeFunctionSig::isUnalignedType() const { return false; } bool NativeTypeFunctionSig::isVolatileType() const { return false; } + +bool NativeTypeFunctionSig::isOptionalType() const { return false; } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp @@ -65,6 +65,7 @@ } dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); + dumpSymbolField(OS, "optionalType", isOptionalType(), Indent); } SymIndexId NativeTypePointer::getClassParentId() const { @@ -149,6 +150,13 @@ PointerOptions::None; } +bool NativeTypePointer::isOptionalType() const { + if (!Record) + return false; + return (Record->getOptions() & PointerOptions::Optional) != + PointerOptions::None; +} + bool NativeTypePointer::isUnalignedType() const { if (!Record) return false; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp @@ -69,6 +69,7 @@ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent); dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); + dumpSymbolField(OS, "optionalType", isOptionalType(), Indent); } std::string NativeTypeUDT::getName() const { @@ -219,3 +220,10 @@ return (Modifiers->Modifiers & ModifierOptions::Volatile) != ModifierOptions::None; } + +bool NativeTypeUDT::isOptionalType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Optional) != + ModifierOptions::None; +} diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp @@ -27,12 +27,15 @@ dumpSymbolField(OS, "constType", isConstType(), Indent); dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); + dumpSymbolField(OS, "optionalType", isOptionalType(), Indent); } bool NativeTypeVTShape::isConstType() const { return false; } bool NativeTypeVTShape::isVolatileType() const { return false; } +bool NativeTypeVTShape::isOptionalType() const { return false; } + bool NativeTypeVTShape::isUnalignedType() const { return false; } uint32_t NativeTypeVTShape::getCount() const { return Record.Slots.size(); } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1121,6 +1121,7 @@ N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || + N.getTag() == dwarf::DW_TAG_LLVM_optional_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp --- a/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp +++ b/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp @@ -339,6 +339,7 @@ IO.bitSetCase(Options, "Restrict", PointerOptions::Restrict); IO.bitSetCase(Options, "WinRTSmartPointer", PointerOptions::WinRTSmartPointer); + IO.bitSetCase(Options, "Optional", PointerOptions::Optional); } void ScalarBitSetTraits::bitset(IO &IO, diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp --- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp +++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp @@ -306,6 +306,7 @@ if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_restrict_type && + Tag != dwarf::DW_TAG_LLVM_optional_type && Tag != dwarf::DW_TAG_member) return false; if (Tag == dwarf::DW_TAG_typedef && !skipTypedef) diff --git a/llvm/lib/Target/BPF/BPFPreserveDIType.cpp b/llvm/lib/Target/BPF/BPFPreserveDIType.cpp --- a/llvm/lib/Target/BPF/BPFPreserveDIType.cpp +++ b/llvm/lib/Target/BPF/BPFPreserveDIType.cpp @@ -89,7 +89,8 @@ while (auto *DTy = dyn_cast(Ty)) { unsigned Tag = DTy->getTag(); if (Tag != dwarf::DW_TAG_const_type && - Tag != dwarf::DW_TAG_volatile_type) + Tag != dwarf::DW_TAG_volatile_type && + Tag != dwarf::DW_TAG_LLVM_optional_type) break; Ty = DTy->getBaseType(); } diff --git a/llvm/lib/Target/BPF/BTF.def b/llvm/lib/Target/BPF/BTF.def --- a/llvm/lib/Target/BPF/BTF.def +++ b/llvm/lib/Target/BPF/BTF.def @@ -34,5 +34,6 @@ HANDLE_BTF_KIND(17, DECL_TAG) HANDLE_BTF_KIND(18, TYPE_TAG) HANDLE_BTF_KIND(19, ENUM64) +HANDLE_BTF_KIND(20, OPTIONAL) #undef HANDLE_BTF_KIND diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -62,6 +62,9 @@ case dwarf::DW_TAG_restrict_type: Kind = BTF::BTF_KIND_RESTRICT; break; + case dwarf::DW_TAG_LLVM_optional_type: + Kind = BTF::BTF_KIND_OPTIONAL; + break; default: llvm_unreachable("Unknown DIDerivedType Tag"); } @@ -91,7 +94,7 @@ const DIType *ResolvedType = DTy->getBaseType(); if (!ResolvedType) { assert((Kind == BTF::BTF_KIND_PTR || Kind == BTF::BTF_KIND_CONST || - Kind == BTF::BTF_KIND_VOLATILE) && + Kind == BTF::BTF_KIND_VOLATILE || Kind == BTF::BTF_KIND_OPTIONAL) && "Invalid null basetype"); BTFType.Type = 0; } else { @@ -826,7 +829,8 @@ } } else if (Tag == dwarf::DW_TAG_typedef || Tag == dwarf::DW_TAG_const_type || Tag == dwarf::DW_TAG_volatile_type || - Tag == dwarf::DW_TAG_restrict_type) { + Tag == dwarf::DW_TAG_restrict_type || + Tag == dwarf::DW_TAG_LLVM_optional_type) { auto TypeEntry = std::make_unique(DTy, Tag, false); TypeId = addType(std::move(TypeEntry), DTy); if (Tag == dwarf::DW_TAG_typedef) @@ -929,7 +933,8 @@ auto Tag = DTy->getTag(); if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && - Tag != dwarf::DW_TAG_restrict_type) + Tag != dwarf::DW_TAG_restrict_type && + Tag != dwarf::DW_TAG_LLVM_optional_type) break; Ty = DTy->getBaseType(); } diff --git a/llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp b/llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp --- a/llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp +++ b/llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp @@ -22,6 +22,8 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; if (Symbol.isVolatileType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; + if (Symbol.isOptionalType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "_Optional "; WithColor(Printer, PDB_ColorItem::Type).get() << getTypeName(Symbol); } diff --git a/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp b/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp --- a/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp +++ b/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp @@ -57,6 +57,8 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; if (Layout.getClass().isUnalignedType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned "; + if (Layout.getClass().isOptionalType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "_Optional "; WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " "; WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName(); diff --git a/llvm/tools/llvm-pdbutil/PrettyEnumDumper.cpp b/llvm/tools/llvm-pdbutil/PrettyEnumDumper.cpp --- a/llvm/tools/llvm-pdbutil/PrettyEnumDumper.cpp +++ b/llvm/tools/llvm-pdbutil/PrettyEnumDumper.cpp @@ -30,6 +30,8 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; if (Symbol.isUnalignedType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned "; + if (Symbol.isOptionalType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "_Optional "; WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum "; WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); return; diff --git a/llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp b/llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp --- a/llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp +++ b/llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp @@ -114,6 +114,8 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; if (Symbol.isVolatileType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; + if (Symbol.isOptionalType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " _Optional"; } void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) { @@ -203,6 +205,8 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; if (Symbol.isVolatileType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; + if (Symbol.isOptionalType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " _Optional"; if (Symbol.isPureVirtual()) Printer << " = 0"; } @@ -257,6 +261,8 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; if (Symbol.isVolatileType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; + if (Symbol.isOptionalType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "_Optional "; PointeeType->dump(*this); Printer << (Symbol.isReference() ? "&" : "*"); diff --git a/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp b/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp --- a/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp +++ b/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp @@ -187,6 +187,8 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; if (Class.isUnalignedType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned "; + if (Class.isOptionalType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "_Optional "; } WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " "; WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName(); diff --git a/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp b/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp --- a/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp +++ b/llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp @@ -57,6 +57,8 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; if (Symbol.isVolatileType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; + if (Symbol.isOptionalType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "_Optional "; auto PointeeType = Symbol.getPointeeType(); if (auto FuncSig = unique_dyn_cast(PointeeType)) { FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer; diff --git a/llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp b/llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp --- a/llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp +++ b/llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp @@ -170,6 +170,8 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; if (Symbol.isVolatileType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; + if (Symbol.isOptionalType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " _Optional"; if (Symbol.getRawSymbol().isRestrictedType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict"; @@ -193,6 +195,8 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << " const "; if (Symbol.isVolatileType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile "; + if (Symbol.isOptionalType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " _Optional "; if (Symbol.getRawSymbol().isRestrictedType()) WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict "; diff --git a/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp b/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp --- a/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp +++ b/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp @@ -395,6 +395,7 @@ MOCK_SYMBOL_ACCESSOR(isVirtualBaseClass) MOCK_SYMBOL_ACCESSOR(isVirtualInheritance) MOCK_SYMBOL_ACCESSOR(isVolatileType) + MOCK_SYMBOL_ACCESSOR(isOptionalType) MOCK_SYMBOL_ACCESSOR(getValue) MOCK_SYMBOL_ACCESSOR(wasInlined) MOCK_SYMBOL_ACCESSOR(getUnused) diff --git a/mlir/include/mlir/IR/Types.h b/mlir/include/mlir/IR/Types.h --- a/mlir/include/mlir/IR/Types.h +++ b/mlir/include/mlir/IR/Types.h @@ -313,7 +313,7 @@ } }; -/// We align TypeStorage by 8, so allow LLVM to steal the low bits. +/// We align TypeStorage by 16, so allow LLVM to steal the low bits. template <> struct PointerLikeTypeTraits { public: @@ -323,7 +323,7 @@ static inline mlir::Type getFromVoidPointer(void *P) { return mlir::Type::getFromOpaquePointer(P); } - static constexpr int NumLowBitsAvailable = 3; + static constexpr int NumLowBitsAvailable = 4; }; /// Add support for llvm style casts. diff --git a/mlir/include/mlir/Support/TypeID.h b/mlir/include/mlir/Support/TypeID.h --- a/mlir/include/mlir/Support/TypeID.h +++ b/mlir/include/mlir/Support/TypeID.h @@ -359,7 +359,7 @@ static inline mlir::TypeID getFromVoidPointer(void *ptr) { return mlir::TypeID::getFromOpaquePointer(ptr); } - static constexpr int NumLowBitsAvailable = 3; + static constexpr int NumLowBitsAvailable = 4; }; } // namespace llvm