Skip to content

Commit

Permalink
[DataFormatters] Add formatter for C++17 std::variant
Browse files Browse the repository at this point in the history
rdar://problem/43691454

Patch by Shafik Yaghmour.

Differential Revision: https://reviews.llvm.org/D51520

llvm-svn: 342563
  • Loading branch information
shafik committed Sep 19, 2018
1 parent 86e5cb0 commit 8306f76
Show file tree
Hide file tree
Showing 9 changed files with 458 additions and 0 deletions.
8 changes: 8 additions & 0 deletions lldb/lldb.xcodeproj/project.pbxproj
Expand Up @@ -401,6 +401,8 @@
AF9FF1F71FAA79FE00474976 /* LibCxxQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF9FF1F61FAA79FE00474976 /* LibCxxQueue.cpp */; };
AF9FF1F51FAA79A400474976 /* LibCxxTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF9FF1F41FAA79A400474976 /* LibCxxTuple.cpp */; };
945261C41B9A11FC00BF138D /* LibCxxUnorderedMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BA1B9A11E800BF138D /* LibCxxUnorderedMap.cpp */; };
E414F6F121388F6C00C50BC6 /* LibCxxVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E414F6F021388F6B00C50BC6 /* LibCxxVariant.cpp */; };
E414F6EE21388F0300C50BC6 /* LibCxxVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = E414F6ED21388F0200C50BC6 /* LibCxxVariant.h */; };
945261C51B9A11FC00BF138D /* LibCxxVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BB1B9A11E800BF138D /* LibCxxVector.cpp */; };
945261C61B9A11FC00BF138D /* LibStdcpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BC1B9A11E800BF138D /* LibStdcpp.cpp */; };
4CDB8D6E1DBA91B6006C5B13 /* LibStdcppTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CDB8D681DBA91A6006C5B13 /* LibStdcppTuple.cpp */; };
Expand Down Expand Up @@ -2056,6 +2058,8 @@
AF9FF1F61FAA79FE00474976 /* LibCxxQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxQueue.cpp; path = Language/CPlusPlus/LibCxxQueue.cpp; sourceTree = "<group>"; };
AF9FF1F41FAA79A400474976 /* LibCxxTuple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxTuple.cpp; path = Language/CPlusPlus/LibCxxTuple.cpp; sourceTree = "<group>"; };
945261BA1B9A11E800BF138D /* LibCxxUnorderedMap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxUnorderedMap.cpp; path = Language/CPlusPlus/LibCxxUnorderedMap.cpp; sourceTree = "<group>"; };
E414F6F021388F6B00C50BC6 /* LibCxxVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxVariant.cpp; path = Language/CPlusPlus/LibCxxVariant.cpp; sourceTree = "<group>"; };
E414F6ED21388F0200C50BC6 /* LibCxxVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibCxxVariant.h; path = Language/CPlusPlus/LibCxxVariant.h; sourceTree = "<group>"; };
945261BB1B9A11E800BF138D /* LibCxxVector.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxVector.cpp; path = Language/CPlusPlus/LibCxxVector.cpp; sourceTree = "<group>"; };
945261BC1B9A11E800BF138D /* LibStdcpp.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibStdcpp.cpp; path = Language/CPlusPlus/LibStdcpp.cpp; sourceTree = "<group>"; };
945261BD1B9A11E800BF138D /* LibStdcpp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LibStdcpp.h; path = Language/CPlusPlus/LibStdcpp.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6475,6 +6479,8 @@
AF9FF1F61FAA79FE00474976 /* LibCxxQueue.cpp */,
AF9FF1F41FAA79A400474976 /* LibCxxTuple.cpp */,
945261BA1B9A11E800BF138D /* LibCxxUnorderedMap.cpp */,
E414F6ED21388F0200C50BC6 /* LibCxxVariant.h */,
E414F6F021388F6B00C50BC6 /* LibCxxVariant.cpp */,
945261BB1B9A11E800BF138D /* LibCxxVector.cpp */,
945261BD1B9A11E800BF138D /* LibStdcpp.h */,
945261BC1B9A11E800BF138D /* LibStdcpp.cpp */,
Expand Down Expand Up @@ -7081,6 +7087,7 @@
6D0F614F1C80AB0C00A4ECEE /* JavaLanguageRuntime.h in Headers */,
AF27AD561D3603EA00CF2833 /* DynamicLoaderDarwin.h in Headers */,
AFCB2BBE1BF577F40018B553 /* PythonExceptionState.h in Headers */,
E414F6EE21388F0300C50BC6 /* LibCxxVariant.h in Headers */,
267F684B1CC02DED0086832B /* ABISysV_s390x.h in Headers */,
AF8AD6311BEC28A400150209 /* PlatformAppleWatchSimulator.h in Headers */,
);
Expand Down Expand Up @@ -7936,6 +7943,7 @@
AF0C112818580CD800C4C45B /* QueueItem.cpp in Sources */,
AF254E31170CCC33007AE5C9 /* PlatformDarwinKernel.cpp in Sources */,
2689004913353E0400698AC0 /* Scalar.cpp in Sources */,
E414F6F121388F6C00C50BC6 /* LibCxxVariant.cpp in Sources */,
263FDE601A79A01500E68013 /* FormatEntity.cpp in Sources */,
AF8AD62E1BEC28A400150209 /* PlatformAppleTVSimulator.cpp in Sources */,
2689004A13353E0400698AC0 /* SearchFilter.cpp in Sources */,
Expand Down
@@ -0,0 +1,7 @@
LEVEL = ../../../../../make

CXX_SOURCES := main.cpp

USE_LIBCPP := 1
include $(LEVEL)/Makefile.rules
CXXFLAGS += -std=c++17
@@ -0,0 +1,81 @@
"""
Test lldb data formatter subsystem.
"""

from __future__ import print_function


import os
import time
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil

class LibcxxOptionalDataFormatterTestCase(TestBase):

mydir = TestBase.compute_mydir(__file__)

@add_test_categories(["libc++"])
## We are skipping clang version less that 5.0 since this test requires -std=c++17
@skipIf(oslist=no_match(["macosx"]), compiler="clang", compiler_version=['<', '5.0'])
## We are skipping gcc version less that 5.1 since this test requires -std=c++17
@skipIf(compiler="gcc", compiler_version=['<', '5.1'])

def test_with_run_command(self):
"""Test that that file and class static variables display correctly."""
self.build()

(self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here',
lldb.SBFileSpec("main.cpp", False))

self.runCmd( "frame variable has_variant" )

output = self.res.GetOutput()

## The variable has_variant tells us if the test program
## detected we have a sufficient libc++ version to support variant
## false means we do not and therefore should skip the test
if output.find("(bool) has_variant = false") != -1 :
self.skipTest( "std::variant not supported" )

lldbutil.continue_to_breakpoint(self.process, bkpt)

self.expect("frame variable v1",
substrs=['v1 = Active Type = int {',
'Value = 12',
'}'])

self.expect("frame variable v1_ref",
substrs=['v1_ref = Active Type = int : {',
'Value = 12',
'}'])

self.expect("frame variable v_v1",
substrs=['v_v1 = Active Type = std::__1::variant<int, double, char> {',
'Value = Active Type = int {',
'Value = 12',
'}',
'}'])

lldbutil.continue_to_breakpoint(self.process, bkpt)

self.expect("frame variable v1",
substrs=['v1 = Active Type = double {',
'Value = 2',
'}'])

lldbutil.continue_to_breakpoint(self.process, bkpt)

self.expect("frame variable v2",
substrs=['v2 = Active Type = double {',
'Value = 2',
'}'])

self.expect("frame variable v3",
substrs=['v3 = Active Type = char {',
'Value = \'A\'',
'}'])

self.expect("frame variable v_no_value",
substrs=['v_no_value = No Value'])
@@ -0,0 +1,60 @@
#include <cstdio>
#include <string>
#include <vector>

// If we have libc++ 4.0 or greater we should have <variant>
// According to libc++ C++1z status page https://libcxx.llvm.org/cxx1z_status.html
#if _LIBCPP_VERSION >= 4000
#include <variant>
#define HAVE_VARIANT 1
#else
#define HAVE_VARIANT 0
#endif

struct S {
operator int() { throw 42; }
} ;


int main()
{
bool has_variant = HAVE_VARIANT ;

printf( "%d\n", has_variant ) ; // break here

#if HAVE_VARIANT == 1
std::variant<int, double, char> v1;
std::variant<int, double, char> &v1_ref = v1;
std::variant<int, double, char> v2;
std::variant<int, double, char> v3;
std::variant<std::variant<int,double,char>> v_v1 ;
std::variant<int, double, char> v_no_value;

v1 = 12; // v contains int
v_v1 = v1 ;
int i = std::get<int>(v1);
printf( "%d\n", i ); // break here

v2 = 2.0 ;
double d = std::get<double>(v2) ;
printf( "%f\n", d );

v3 = 'A' ;
char c = std::get<char>(v3) ;
printf( "%d\n", c );

// Checking v1 above and here to make sure we done maintain the incorrect
// state when we change its value.
v1 = 2.0;
d = std::get<double>(v1) ;
printf( "%f\n", d ); // break here

try {
v_no_value.emplace<0>(S());
} catch( ... ) {}

printf( "%zu\n", v_no_value.index() ) ;
#endif

return 0; // break here
}
1 change: 1 addition & 0 deletions lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
Expand Up @@ -13,6 +13,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibCxxQueue.cpp
LibCxxTuple.cpp
LibCxxUnorderedMap.cpp
LibCxxVariant.cpp
LibCxxVector.cpp
LibStdcpp.cpp
LibStdcppTuple.cpp
Expand Down
10 changes: 10 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
Expand Up @@ -39,6 +39,7 @@
#include "CxxStringTypes.h"
#include "LibCxx.h"
#include "LibCxxAtomic.h"
#include "LibCxxVariant.h"
#include "LibStdcpp.h"

using namespace lldb;
Expand Down Expand Up @@ -516,6 +517,10 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"libc++ std::optional synthetic children",
ConstString("^std::__(ndk)?1::optional<.+>(( )?&)?$"),
stl_synth_flags, true);
AddCXXSynthetic(cpp_category_sp, LibcxxVariantFrontEndCreator,
"libc++ std::variant synthetic children",
ConstString("^std::__(ndk)?1::variant<.+>(( )?&)?$"),
stl_synth_flags, true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,
Expand Down Expand Up @@ -617,6 +622,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"libc++ std::optional summary provider",
ConstString("^std::__(ndk)?1::optional<.+>(( )?&)?$"),
stl_summary_flags, true);
AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxVariantSummaryProvider,
"libc++ std::variant summary provider",
ConstString("^std::__(ndk)?1::variant<.+>(( )?&)?$"),
stl_summary_flags, true);

stl_summary_flags.SetSkipPointers(true);

Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
Expand Up @@ -142,6 +142,10 @@ SyntheticChildrenFrontEnd *
LibcxxOptionalFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP valobj_sp);

SyntheticChildrenFrontEnd *
LibcxxVariantFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP valobj_sp);

} // namespace formatters
} // namespace lldb_private

Expand Down

0 comments on commit 8306f76

Please sign in to comment.