Index: lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -196,6 +196,24 @@
   return ret;
 }
 
+/// Returns true if LLDB can take the address of the given lvalue for the sake
+/// of capturing the expression result. Returns false if LLDB should instead
+/// store the expression result in a result variable.
+static bool CanTakeAddressOfLValue(const Expr *lvalue_expr) {
+  QualType qt = lvalue_expr->getType();
+  // If the lvalue has const-qualified non-volatile integral or enum type, then
+  // the underlying value might come from a const static data member as
+  // described in C++11 [class.static.data]p3. If that's the case, then the
+  // value might not have an address if the user didn't also define the member
+  // in a namespace scope. Taking the address would cause that LLDB later fails
+  // to link the expression, so those lvalues should be stored in a result
+  // variable.
+  if (qt->isIntegralOrEnumerationType() && qt.isConstQualified() &&
+      !qt.isVolatileQualified())
+    return false;
+  return true;
+}
+
 bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
                                                 DeclContext *DC) {
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@@ -303,7 +321,7 @@
 
   clang::VarDecl *result_decl = nullptr;
 
-  if (is_lvalue) {
+  if (is_lvalue && CanTakeAddressOfLValue(last_expr)) {
     IdentifierInfo *result_ptr_id;
 
     if (expr_type->isFunctionType())
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -67,6 +67,10 @@
 
   lldb_private::ClangASTImporter &GetClangASTImporter();
 
+  llvm::Expected<llvm::APInt>
+  ExtractIntFromFormValue(const lldb_private::CompilerType &ct,
+                          const DWARFFormValue &form_value) const;
+
 protected:
   /// Protected typedefs and members.
   /// @{
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2383,6 +2383,45 @@
   return nullptr;
 }
 
+llvm::Expected<llvm::APInt> DWARFASTParserClang::ExtractIntFromFormValue(
+    const CompilerType &ct, const DWARFFormValue &form_value) const {
+  clang::QualType qt = ClangUtil::GetQualType(ct);
+  assert(qt->isIntegralOrEnumerationType());
+  TypeSystemClang &ts = *llvm::cast<TypeSystemClang>(ct.GetTypeSystem());
+  clang::ASTContext &ast = ts.getASTContext();
+
+  const bool is_unsigned = qt->isUnsignedIntegerType();
+  const unsigned type_bits = ast.getIntWidth(qt);
+
+  llvm::APSInt result(
+      llvm::APInt(sizeof(uint64_t) * 8, form_value.Unsigned(), !is_unsigned),
+      is_unsigned);
+
+  bool failed = false;
+  if (is_unsigned) {
+    failed = result.getActiveBits() > type_bits;
+  } else {
+    failed = result.getMinSignedBits() > type_bits;
+  }
+  if (failed) {
+    std::string value_as_str = is_unsigned
+                                   ? std::to_string(form_value.Unsigned())
+                                   : std::to_string(form_value.Signed());
+    llvm::errs() << "##########\n";
+    llvm::errs() << "Active " << result.getActiveBits() << "\n";
+    llvm::errs() << "getMinSignedBits " << result.getMinSignedBits() << "\n";
+    llvm::errs() << "Value: " << value_as_str << "\n";
+    auto msg = llvm::formatv("Can't store {0} value {1} in integer with {2} "
+                             "bits.",
+                             (is_unsigned ? "unsigned" : "signed"),
+                             value_as_str, type_bits);
+    return llvm::createStringError(llvm::inconvertibleErrorCode(), msg.str());
+  }
+  if (result.getBitWidth() > type_bits)
+    result = result.trunc(type_bits);
+  return result;
+}
+
 void DWARFASTParserClang::ParseSingleMember(
     const DWARFDIE &die, const DWARFDIE &parent_die,
     const lldb_private::CompilerType &class_clang_type,
@@ -2392,6 +2431,9 @@
     DelayedPropertyList &delayed_properties,
     lldb_private::ClangASTImporter::LayoutInfo &layout_info,
     FieldInfo &last_field_info) {
+  Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_TYPE_COMPLETION |
+                                          DWARF_LOG_LOOKUPS);
+
   ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
   const dw_tag_t tag = die.Tag();
   // Get the parent byte size so we can verify any members will fit
@@ -2418,6 +2460,7 @@
     int64_t bit_offset = 0;
     uint64_t data_bit_offset = UINT64_MAX;
     size_t bit_size = 0;
+    llvm::Optional<DWARFFormValue> const_value_form;
     bool is_external =
         false; // On DW_TAG_members, this means the member is static
     uint32_t i;
@@ -2449,6 +2492,9 @@
         case DW_AT_byte_size:
           byte_size = form_value.Unsigned();
           break;
+        case DW_AT_const_value:
+          const_value_form = form_value;
+          break;
         case DW_AT_data_bit_offset:
           data_bit_offset = form_value.Unsigned();
           break;
@@ -2572,9 +2618,21 @@
       if (var_type) {
         if (accessibility == eAccessNone)
           accessibility = eAccessPublic;
-        TypeSystemClang::AddVariableToRecordType(
-            class_clang_type, name, var_type->GetLayoutCompilerType(),
-            accessibility);
+        CompilerType ct = var_type->GetLayoutCompilerType();
+        clang::VarDecl *v = TypeSystemClang::AddVariableToRecordType(
+            class_clang_type, name, ct, accessibility);
+
+        if (!const_value_form)
+          return;
+        llvm::Expected<llvm::APInt> const_value_or_err =
+            ExtractIntFromFormValue(ct, *const_value_form);
+        if (!const_value_or_err) {
+          LLDB_LOG_ERROR(log, const_value_or_err.takeError(),
+                         "Failed to add const value to variable {1}: {0}",
+                         v->getQualifiedNameAsString());
+          return;
+        }
+        TypeSystemClang::AddInitToVarDecl(v, *const_value_or_err);
       }
       return;
     }
Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
===================================================================
--- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -873,6 +873,9 @@
                                                  const CompilerType &var_type,
                                                  lldb::AccessType access);
 
+  static void AddInitToVarDecl(clang::VarDecl *v,
+                               const llvm::APInt &init_value);
+
   clang::CXXMethodDecl *AddMethodToCXXRecordType(
       lldb::opaque_compiler_type_t type, llvm::StringRef name,
       const char *mangled_name, const CompilerType &method_type,
Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
===================================================================
--- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -7279,6 +7279,19 @@
   return var_decl;
 }
 
+void TypeSystemClang::AddInitToVarDecl(VarDecl *v,
+                                       const llvm::APInt &init_value) {
+  clang::ASTContext &ast = v->getASTContext();
+  QualType qt = v->getType();
+  assert(qt->isIntegralOrEnumerationType());
+  if (const EnumType *enum_type = llvm::dyn_cast<EnumType>(qt.getTypePtr())) {
+    const EnumDecl *enum_decl = enum_type->getDecl();
+    qt = enum_decl->getIntegerType();
+  }
+  v->setInit(IntegerLiteral::Create(ast, init_value, qt.getUnqualifiedType(),
+                                    SourceLocation()));
+}
+
 clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
     lldb::opaque_compiler_type_t type, llvm::StringRef name,
     const char *mangled_name, const CompilerType &method_clang_type,
Index: lldb/source/Utility/DataExtractor.cpp
===================================================================
--- lldb/source/Utility/DataExtractor.cpp
+++ lldb/source/Utility/DataExtractor.cpp
@@ -33,6 +33,7 @@
 #include <cstdint>
 #include <string>
 
+#include "llvm/Support/LEB128.h"
 #include <ctype.h>
 #include <inttypes.h>
 #include <string.h>
@@ -877,26 +878,10 @@
   if (src == nullptr)
     return 0;
 
-  const uint8_t *end = m_end;
-
-  if (src < end) {
-    uint64_t result = *src++;
-    if (result >= 0x80) {
-      result &= 0x7f;
-      int shift = 7;
-      while (src < end) {
-        uint8_t byte = *src++;
-        result |= static_cast<uint64_t>(byte & 0x7f) << shift;
-        if ((byte & 0x80) == 0)
-          break;
-        shift += 7;
-      }
-    }
-    *offset_ptr = src - m_start;
-    return result;
-  }
-
-  return 0;
+  unsigned byte_count = 0;
+  uint64_t result = llvm::decodeULEB128(src, &byte_count, src + 9);
+  *offset_ptr += byte_count;
+  return result;
 }
 
 // Extracts an signed LEB128 number from this object's data starting at the
@@ -910,35 +895,10 @@
   if (src == nullptr)
     return 0;
 
-  const uint8_t *end = m_end;
-
-  if (src < end) {
-    int64_t result = 0;
-    int shift = 0;
-    int size = sizeof(int64_t) * 8;
-
-    uint8_t byte = 0;
-    int bytecount = 0;
-
-    while (src < end) {
-      bytecount++;
-      byte = *src++;
-      result |= static_cast<int64_t>(byte & 0x7f) << shift;
-      shift += 7;
-      if ((byte & 0x80) == 0)
-        break;
-    }
-
-    // Sign bit of byte is 2nd high order bit (0x40)
-    if (shift < size && (byte & 0x40)) {
-      // -(static_cast<int64_t>(1) << 63) errors on the negation with UBSan.
-      result |= -(static_cast<uint64_t>(1) << shift);
-    }
-
-    *offset_ptr += bytecount;
-    return result;
-  }
-  return 0;
+  unsigned byte_count = 0;
+  int64_t result = llvm::decodeSLEB128(src, &byte_count, src + 9);
+  *offset_ptr += byte_count;
+  return result;
 }
 
 // Skips a ULEB128 number (signed or unsigned) from this object's data starting
Index: lldb/test/API/lang/cpp/const_static_integral_member/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/const_static_integral_member/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
Index: lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py
@@ -0,0 +1,75 @@
+"""
+Tests const static data members as specified by C++11 [class.static.data]p3.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def test(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.cpp"))
+
+        # Test using a simple const static integer member.
+        self.expect_expr("A::int_val", result_value="1")
+
+        # Try accessing the int member via some expressions that still produce
+        # an lvalue.
+        self.expect_expr("a.int_val", result_value="1")
+        self.expect_expr("(A::int_val)", result_value="1")
+        self.expect_expr("+A::int_val", result_value="1")
+        self.expect_expr("1,A::int_val", result_value="1")
+        self.expect_expr("true ? A::int_val : A::int_val", result_value="1")
+
+        # Test a simple integer member that was also defined in a namespace
+        # scope and has an address.
+        self.expect_expr("A::int_val_with_address", result_value="2")
+
+        # Try to take the address of the data member. Should produce a linker
+        # error only if the member doesn't have an address.
+        self.expect("expr const int *i = &A::int_val; *i", error=True,
+                    substrs=["Couldn't lookup symbols:"])
+        self.expect_expr("const int *i = &A::int_val_with_address; *i",
+                         result_value="2")
+
+        # Test a bool member.
+        self.expect_expr("A::bool_val", result_value="true")
+
+        # Test that minimum and maximum values for each data type are right.
+        self.expect_expr("A::char_max == char_max", result_value="true")
+        self.expect_expr("A::uchar_max == uchar_max", result_value="true")
+        self.expect_expr("A::int_max == int_max", result_value="true")
+        self.expect_expr("A::uint_max == uint_max", result_value="true")
+        self.expect_expr("A::long_max == long_max", result_value="true")
+        self.expect_expr("A::ulong_max == ulong_max", result_value="true")
+        self.expect_expr("A::longlong_max == longlong_max", result_value="true")
+        self.expect_expr("A::ulonglong_max == ulonglong_max", result_value="true")
+
+        self.expect_expr("A::char_min == char_min", result_value="true")
+        self.expect_expr("A::uchar_min == uchar_min", result_value="true")
+        self.expect_expr("A::int_min == int_min", result_value="true")
+        self.expect_expr("A::uint_min == uint_min", result_value="true")
+        self.expect_expr("A::long_min == long_min", result_value="true")
+        self.expect_expr("A::ulong_min == ulong_min", result_value="true")
+        self.expect_expr("A::longlong_min == longlong_min", result_value="true")
+        self.expect_expr("A::ulonglong_min == ulonglong_min", result_value="true")
+
+        # Test an unscoped enum.
+        self.expect_expr("A::enum_val", result_value="enum_case2")
+        # Test an unscoped enum with an invalid enum case.
+        self.expect_expr("A::invalid_enum_val", result_value="enum_case1 | enum_case2 | 0x4")
+
+        # Test a scoped enum.
+        self.expect_expr("A::scoped_enum_val", result_value="scoped_enum_case2")
+        # Test an scoped enum with an invalid enum case.
+        self.expect_expr("A::invalid_scoped_enum_val", result_value="scoped_enum_case1 | 0x4")
+
+        # Test an enum with fixed underlying type.
+        self.expect_expr("A::scoped_char_enum_val", result_value="case2")
+        self.expect_expr("A::scoped_ll_enum_val_neg", result_value="case0")
+        self.expect_expr("A::scoped_ll_enum_val", result_value="case2")
Index: lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
@@ -0,0 +1,90 @@
+#include <limits>
+
+enum Enum {
+  enum_case1 = 1,
+  enum_case2 = 2,
+};
+
+enum class ScopedEnum {
+  scoped_enum_case1 = 1,
+  scoped_enum_case2 = 2,
+};
+
+enum class ScopedCharEnum : char {
+  case1 = 1,
+  case2 = 2,
+};
+
+enum class ScopedLongLongEnum : long long {
+  case0 = std::numeric_limits<long long>::min(),
+  case1 = 1,
+  case2 = std::numeric_limits<long long>::max(),
+};
+
+struct A {
+  const static int int_val = 1;
+  const static int int_val_with_address = 2;
+  const static bool bool_val = true;
+
+  const static auto char_max = std::numeric_limits<signed char>::max();
+  const static auto uchar_max = std::numeric_limits<unsigned char>::max();
+  const static auto int_max = std::numeric_limits<int>::max();
+  const static auto uint_max = std::numeric_limits<unsigned>::max();
+  const static auto long_max = std::numeric_limits<long>::max();
+  const static auto ulong_max = std::numeric_limits<unsigned long>::max();
+  const static auto longlong_max = std::numeric_limits<long long>::max();
+  const static auto ulonglong_max =
+      std::numeric_limits<unsigned long long>::max();
+
+  const static auto char_min = std::numeric_limits<char>::min();
+  const static auto uchar_min = std::numeric_limits<unsigned char>::min();
+  const static auto int_min = std::numeric_limits<int>::min();
+  const static auto uint_min = std::numeric_limits<unsigned>::min();
+  const static auto long_min = std::numeric_limits<long>::min();
+  const static auto ulong_min = std::numeric_limits<unsigned long>::min();
+  const static auto longlong_min = std::numeric_limits<long long>::min();
+  const static auto ulonglong_min =
+      std::numeric_limits<unsigned long long>::min();
+
+  const static Enum enum_val = enum_case2;
+  const static Enum invalid_enum_val = static_cast<Enum>(enum_case2 + 5);
+  const static ScopedEnum scoped_enum_val = ScopedEnum::scoped_enum_case2;
+  const static ScopedEnum invalid_scoped_enum_val = static_cast<ScopedEnum>(5);
+  const static ScopedCharEnum scoped_char_enum_val = ScopedCharEnum::case2;
+  const static ScopedLongLongEnum scoped_ll_enum_val_neg =
+      ScopedLongLongEnum::case0;
+  const static ScopedLongLongEnum scoped_ll_enum_val =
+      ScopedLongLongEnum::case2;
+};
+
+const int A::int_val_with_address;
+
+int main() {
+  A a;
+
+  auto char_max = A::char_max;
+  auto uchar_max = A::uchar_max;
+  auto int_max = A::int_max;
+  auto uint_max = A::uint_max;
+  auto long_max = A::long_max;
+  auto ulong_max = A::ulong_max;
+  auto longlong_max = A::longlong_max;
+  auto ulonglong_max = A::ulonglong_max;
+
+  auto char_min = A::char_min;
+  auto uchar_min = A::uchar_min;
+  auto int_min = A::int_min;
+  auto uint_min = A::uint_min;
+  auto long_min = A::long_min;
+  auto ulong_min = A::ulong_min;
+  auto longlong_min = A::longlong_min;
+  auto ulonglong_min = A::ulonglong_min;
+
+  Enum e = A::enum_val;
+  e = A::invalid_enum_val;
+  ScopedEnum se = A::scoped_enum_val;
+  se = A::invalid_scoped_enum_val;
+  ScopedCharEnum sce = A::scoped_char_enum_val;
+  ScopedLongLongEnum sle = A::scoped_ll_enum_val;
+  return 0; // break here
+}
Index: lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
===================================================================
--- lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
+++ lldb/unittests/SymbolFile/DWARF/CMakeLists.txt
@@ -13,6 +13,7 @@
     lldbPluginTypeSystemClang
     lldbUtilityHelpers
     lldbPluginPlatformMacOSX
+    LLVMTestingSupport
   LINK_COMPONENTS
     Support
     DebugInfoPDB
Index: lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
===================================================================
--- lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -17,7 +17,7 @@
 using namespace lldb_private;
 
 namespace {
-class DWARFASTParserClangTests : public testing::Test {};
+class DWARFASTParserClangStubTests : public testing::Test {};
 
 class DWARFASTParserClangStub : public DWARFASTParserClang {
 public:
@@ -35,7 +35,7 @@
 
 // If your implementation needs to dereference the dummy pointers we are
 // defining here, causing this test to fail, feel free to delete it.
-TEST_F(DWARFASTParserClangTests,
+TEST_F(DWARFASTParserClangStubTests,
        EnsureAllDIEsInDeclContextHaveBeenParsedParsesOnlyMatchingEntries) {
 
   /// Auxiliary debug info.
@@ -116,3 +116,95 @@
               testing::UnorderedElementsAre(decl_ctxs[0], decl_ctxs[3]));
 }
 
+struct ExtractIntFromFormValueTest : public testing::Test {
+  SubsystemRAII<FileSystem, HostInfo> subsystems;
+  TypeSystemClang ts;
+  DWARFASTParserClang parser;
+  ExtractIntFromFormValueTest()
+      : ts("dummy ASTContext", HostInfoBase::GetTargetTriple()), parser(ts) {}
+
+  llvm::Expected<std::string> Extract(clang::QualType qt, uint64_t value) {
+    DWARFFormValue form_value;
+    form_value.SetUnsigned(value);
+    llvm::Expected<llvm::APInt> result = parser.ExtractIntFromFormValue(ts.GetType(qt), form_value);
+    if (!result)
+      return result.takeError();
+    llvm::SmallString<16> result_str;
+    result->toStringUnsigned(result_str);
+    return std::string(result_str.str());
+  }
+
+  llvm::Expected<std::string> ExtractS(clang::QualType qt, int64_t value) {
+    DWARFFormValue form_value;
+    form_value.SetSigned(value);
+    llvm::Expected<llvm::APInt> result = parser.ExtractIntFromFormValue(ts.GetType(qt), form_value);
+    if (!result)
+      return result.takeError();
+    llvm::SmallString<16> result_str;
+    result->toStringSigned(result_str);
+    return std::string(result_str.str());
+  }
+};
+
+TEST_F(ExtractIntFromFormValueTest, TestBool) {
+  using namespace llvm;
+  clang::ASTContext &ast = ts.getASTContext();
+
+  EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 0), HasValue("0"));
+  EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 1), HasValue("1"));
+  EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 2), Failed());
+  EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 3), Failed());
+}
+
+TEST_F(ExtractIntFromFormValueTest, TestInt) {
+  using namespace llvm;
+
+  clang::ASTContext &ast = ts.getASTContext();
+  const int64_t int_max = (static_cast<uint64_t>(1)
+                          << (ast.getIntWidth(ast.IntTy) - 1)) - 1U;
+  const int64_t int_min = -int_max - 1;
+
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min - 2),
+                    llvm::Failed());
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min - 1),
+                    llvm::Failed());
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min), HasValue(std::to_string(int_min)));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min + 1),
+            HasValue(std::to_string(int_min + 1)));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min + 2),
+            HasValue(std::to_string(int_min + 2)));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, -10), HasValue("-10"));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, -1), HasValue("-1"));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 0), HasValue("0"));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 1), HasValue("1"));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 10), HasValue("10"));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max - 2),
+                       HasValue(std::to_string(int_max - 2)));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max - 1),
+                       HasValue(std::to_string(int_max - 1)));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max),
+                       HasValue(std::to_string(int_max)));
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max + 1),
+                    llvm::Failed());
+  EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max + 5),
+                    llvm::Failed());
+}
+
+TEST_F(ExtractIntFromFormValueTest, TestUnsignedInt) {
+  using namespace llvm;
+
+  clang::ASTContext &ast = ts.getASTContext();
+  const uint64_t uint_max =
+      (static_cast<uint64_t>(1) << ast.getIntWidth(ast.UnsignedIntTy)) - 1U;
+
+  EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, 0), HasValue("0"));
+  EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, 1), HasValue("1"));
+  EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, 1234), HasValue("1234"));
+  EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max - 1),
+            HasValue(std::to_string(uint_max - 1)));
+  EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max),
+            HasValue(std::to_string(uint_max)));
+  EXPECT_THAT_EXPECTED(
+      Extract(ast.UnsignedIntTy, uint_max + 1),
+      llvm::Failed());
+}