chrisbazley created this revision.
Herald added subscribers: Moerafaat, zero9178, bzcheeseman, sdasgup3, 
wenzhicui, wrengr, cota, teijeong, rdzhabarov, tatianashp, jdoerfert, 
msifontes, jurahul, Kayjukh, grosul1, Joonsoo, liufengdb, aartbik, mgester, 
arpith-jacob, antiagainst, shauheen, rriddle, mehdi_amini, thopre, martong, 
hiraditya.
Herald added a reviewer: shafik.
Herald added a reviewer: shafik.
Herald added a reviewer: rriddle.
Herald added a project: All.
chrisbazley requested review of this revision.
Herald added subscribers: llvm-commits, lldb-commits, cfe-commits, 
stephenneuendorffer, nicolasvasilache.
Herald added projects: clang, LLDB, MLIR, LLVM.

A new pointee type qualifier for the purpose of
adding pointer nullability information to C
programs. Its goal is to provide value not only
for static analysis and documentation, but also
for compilers which report errors based only on
existing type-compatibility rules. The syntax
and semantics are designed to be as familiar (to
C programmers) and ergonomic as possible.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142733

Files:
  clang/include/clang/AST/APValue.h
  clang/include/clang/AST/CanonicalType.h
  clang/include/clang/AST/Type.h
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/DeclSpec.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/TypePrinter.cpp
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/Format/FormatToken.h
  clang/lib/Format/QualifierAlignmentFixer.cpp
  clang/lib/Format/TokenAnnotator.cpp
  clang/lib/Format/UnwrappedLineParser.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseObjc.cpp
  clang/lib/Parse/ParseTentative.cpp
  clang/lib/Sema/DeclSpec.cpp
  clang/lib/Sema/SemaCodeComplete.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaDeclObjC.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaType.cpp
  lldb/include/lldb/Symbol/Type.h
  lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
  lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
  lldb/source/Symbol/Type.cpp
  llvm/docs/LangRef.rst
  llvm/docs/SourceLevelDebugging.rst
  llvm/include/llvm/BinaryFormat/Dwarf.def
  llvm/include/llvm/DebugInfo/CodeView/CodeView.h
  llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h
  llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
  llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
  llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
  llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
  llvm/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h
  llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h
  llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h
  llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h
  llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h
  llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h
  llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h
  llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
  llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
  llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
  llvm/lib/DWARFLinker/DWARFLinker.cpp
  llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
  llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp
  llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
  llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
  llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
  llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp
  llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp
  llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
  llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp
  llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp
  llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
  llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp
  llvm/lib/IR/Verifier.cpp
  llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp
  llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
  llvm/lib/Target/BPF/BPFPreserveDIType.cpp
  llvm/lib/Target/BPF/BTF.def
  llvm/lib/Target/BPF/BTFDebug.cpp
  llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp
  llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp
  llvm/tools/llvm-pdbutil/PrettyEnumDumper.cpp
  llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp
  llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp
  llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp
  llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp
  llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
  mlir/include/mlir/IR/Types.h
  mlir/include/mlir/Support/TypeID.h

Index: mlir/include/mlir/Support/TypeID.h
===================================================================
--- mlir/include/mlir/Support/TypeID.h
+++ 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
Index: mlir/include/mlir/IR/Types.h
===================================================================
--- mlir/include/mlir/IR/Types.h
+++ 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<mlir::Type> {
 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.
Index: llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
===================================================================
--- llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
+++ 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)
Index: llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp
===================================================================
--- llvm/tools/llvm-pdbutil/PrettyVariableDumper.cpp
+++ 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 ";
Index: llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp
===================================================================
--- llvm/tools/llvm-pdbutil/PrettyTypedefDumper.cpp
+++ 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<PDBSymbolTypeFunctionSig>(PointeeType)) {
     FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer;
Index: llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp
===================================================================
--- llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp
+++ 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();
Index: llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp
===================================================================
--- llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp
+++ 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() ? "&" : "*");
 
Index: llvm/tools/llvm-pdbutil/PrettyEnumDumper.cpp
===================================================================
--- llvm/tools/llvm-pdbutil/PrettyEnumDumper.cpp
+++ 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;
Index: llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp
===================================================================
--- llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp
+++ 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();
Index: llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp
===================================================================
--- llvm/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp
+++ 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);
 }
 
Index: llvm/lib/Target/BPF/BTFDebug.cpp
===================================================================
--- llvm/lib/Target/BPF/BTFDebug.cpp
+++ 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<BTFTypeDerived>(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();
   }
Index: llvm/lib/Target/BPF/BTF.def
===================================================================
--- llvm/lib/Target/BPF/BTF.def
+++ 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
Index: llvm/lib/Target/BPF/BPFPreserveDIType.cpp
===================================================================
--- llvm/lib/Target/BPF/BPFPreserveDIType.cpp
+++ llvm/lib/Target/BPF/BPFPreserveDIType.cpp
@@ -89,7 +89,8 @@
       while (auto *DTy = dyn_cast<DIDerivedType>(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();
       }
Index: llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
===================================================================
--- llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
+++ 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)
Index: llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp
===================================================================
--- llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp
+++ 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<ModifierOptions>::bitset(IO &IO,
Index: llvm/lib/IR/Verifier.cpp
===================================================================
--- llvm/lib/IR/Verifier.cpp
+++ 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 ||
Index: llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp
+++ 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(); }
Index: llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
+++ 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;
+}
Index: llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp
+++ 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;
Index: llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp
+++ 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<IPDBEnumSymbols>
@@ -198,3 +199,5 @@
 bool NativeTypeFunctionSig::isUnalignedType() const { return false; }
 
 bool NativeTypeFunctionSig::isVolatileType() const { return false; }
+
+bool NativeTypeFunctionSig::isOptionalType() const { return false; }
Index: llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
+++ 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<IPDBEnumSymbols>
@@ -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;
Index: llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp
+++ 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;
+}
Index: llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp
+++ 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());
Index: llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
+++ 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 {
Index: llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
+++ 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;
 }
Index: llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
===================================================================
--- llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
+++ 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);
 }
Index: llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp
===================================================================
--- llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp
+++ 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))
Index: llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
===================================================================
--- llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ 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);
Index: llvm/lib/DWARFLinker/DWARFLinker.cpp
===================================================================
--- llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ 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:
Index: llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ 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());
   }
Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ 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<DIDerivedType>(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<DIDerivedType>(Ty)->getBaseType();
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
+++ 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
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
+++ 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<IPDBEnumLineNumbers> getLineNumbers() const;
   uint32_t getCompilandId() const;
Index: llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h
+++ 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<IPDBEnumLineNumbers> getLineNumbers() const;
   uint32_t getCompilandId() const;
Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h
+++ 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;
 
Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h
+++ 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;
Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h
+++ 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;
Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h
+++ 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);
Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h
+++ 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;
Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h
+++ 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;
Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h
+++ 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;
Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h
+++ 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;
 
Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
+++ 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;
 
Index: llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
+++ 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;
 };
Index: llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
===================================================================
--- llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
+++ 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;
 
Index: llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
===================================================================
--- llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h
+++ 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);
 };
 
Index: llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h
===================================================================
--- llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h
+++ 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));
   }
Index: llvm/include/llvm/DebugInfo/CodeView/CodeView.h
===================================================================
--- llvm/include/llvm/DebugInfo/CodeView/CodeView.h
+++ 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
Index: llvm/include/llvm/BinaryFormat/Dwarf.def
===================================================================
--- llvm/include/llvm/BinaryFormat/Dwarf.def
+++ 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)
Index: llvm/docs/SourceLevelDebugging.rst
===================================================================
--- llvm/docs/SourceLevelDebugging.rst
+++ 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
Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ 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.
 
Index: lldb/source/Symbol/Type.cpp
===================================================================
--- lldb/source/Symbol/Type.cpp
+++ 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;
Index: lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ 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<uint64_t> 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,
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ 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;
 }
 
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ 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(
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ 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;
               }
             }
           }
Index: lldb/include/lldb/Symbol/Type.h
===================================================================
--- lldb/include/lldb/Symbol/Type.h
+++ 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 {
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ 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());
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -1366,9 +1366,11 @@
     if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() &&
         !isa<CXXConstructorDecl>(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;
   }
Index: clang/lib/Sema/SemaDeclObjC.cpp
===================================================================
--- clang/lib/Sema/SemaDeclObjC.cpp
+++ clang/lib/Sema/SemaDeclObjC.cpp
@@ -1613,6 +1613,7 @@
                                                 SourceLocation(),
                                                 SourceLocation(),
                                                 SourceLocation(),
+                                                SourceLocation(),
                                                 SourceLocation()),
                                                 starLoc);
 
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ 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)
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ 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)
Index: clang/lib/Sema/SemaCodeComplete.cpp
===================================================================
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ 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))
Index: clang/lib/Sema/DeclSpec.cpp
===================================================================
--- clang/lib/Sema/DeclSpec.cpp
+++ 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) {
Index: clang/lib/Parse/ParseTentative.cpp
===================================================================
--- clang/lib/Parse/ParseTentative.cpp
+++ 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();
 
Index: clang/lib/Parse/ParseObjc.cpp
===================================================================
--- clang/lib/Parse/ParseObjc.cpp
+++ 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:
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ 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;
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ 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(),
Index: clang/lib/Format/UnwrappedLineParser.cpp
===================================================================
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ 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);
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ 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
Index: clang/lib/Format/QualifierAlignmentFixer.cpp
===================================================================
--- clang/lib/Format/QualifierAlignmentFixer.cpp
+++ 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)
Index: clang/lib/Format/FormatToken.h
===================================================================
--- clang/lib/Format/FormatToken.h
+++ 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);
   }
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ 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)
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ 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) {
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -1708,9 +1708,10 @@
   Out << 'N';
   if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(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());
   }
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ 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
   };
 
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ 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());
Index: clang/include/clang/Sema/DeclSpec.h
===================================================================
--- clang/include/clang/Sema/DeclSpec.h
+++ 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;
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ 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)
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ 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">;
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ 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,
Index: clang/include/clang/AST/CanonicalType.h
===================================================================
--- clang/include/clang/AST/CanonicalType.h
+++ 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.
Index: clang/include/clang/AST/APValue.h
===================================================================
--- clang/include/clang/AST/APValue.h
+++ clang/include/clang/AST/APValue.h
@@ -86,7 +86,7 @@
     return (std::numeric_limits<unsigned>::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<clang::DynamicAllocLValue> {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D142733: ... Christopher Bazley via Phabricator via cfe-commits

Reply via email to