Index: lldb/trunk/include/lldb/Symbol/ClangASTContext.h =================================================================== --- lldb/trunk/include/lldb/Symbol/ClangASTContext.h +++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h @@ -726,13 +726,16 @@ // Exploring the type //---------------------------------------------------------------------- - uint64_t GetByteSize(lldb::opaque_compiler_type_t type, + llvm::Optional GetByteSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) { - return (GetBitSize(type, exe_scope) + 7) / 8; + if (llvm::Optional bit_size = GetBitSize(type, exe_scope)) + return (*bit_size + 7) / 8; + return llvm::None; } - uint64_t GetBitSize(lldb::opaque_compiler_type_t type, - ExecutionContextScope *exe_scope) override; + llvm::Optional + GetBitSize(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) override; lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) override; Index: lldb/trunk/include/lldb/Symbol/TypeSystem.h =================================================================== --- lldb/trunk/include/lldb/Symbol/TypeSystem.h +++ lldb/trunk/include/lldb/Symbol/TypeSystem.h @@ -271,8 +271,9 @@ // Exploring the type //---------------------------------------------------------------------- - virtual uint64_t GetBitSize(lldb::opaque_compiler_type_t type, - ExecutionContextScope *exe_scope) = 0; + virtual llvm::Optional + GetBitSize(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) = 0; virtual lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) = 0; Index: lldb/trunk/lit/SymbolFile/NativePDB/function-types-builtins.cpp =================================================================== --- lldb/trunk/lit/SymbolFile/NativePDB/function-types-builtins.cpp +++ lldb/trunk/lit/SymbolFile/NativePDB/function-types-builtins.cpp @@ -186,17 +186,17 @@ // Function references, we only need a couple of these since most of the // interesting cases are already tested. auto &ref = unary; -// CHECK: (void (&)(bool)) ref = {{.*}} (&::ref = ) +// CHECK: (void (&)(bool)) ref = {{.*}} (&::ref = ) auto &ref2 = unary; -// CHECK: (void (&)(volatile int *)) ref2 = {{.*}} (&::ref2 = ) +// CHECK: (void (&)(volatile int *)) ref2 = {{.*}} (&::ref2 = ) auto &ref3 = varargs; -// CHECK: (int (&)(int, int, ...)) ref3 = {{.*}} (&::ref3 = ) +// CHECK: (int (&)(int, int, ...)) ref3 = {{.*}} (&::ref3 = ) // Multiple arguments, as before, just something to make sure it works. auto binp = &binary; // CHECK: (void (*)(int *, const int *)) binp = {{.*}} auto &binr = binary; -// CHECK: (void (&)(int *, const int *)) binr = {{.*}} (&::binr = ) +// CHECK: (void (&)(int *, const int *)) binr = {{.*}} (&::binr = ) // And finally, a function with no arguments. auto null = &nullary; Index: lldb/trunk/packages/Python/lldbsuite/test/lang/c/struct_types/main.c =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/c/struct_types/main.c +++ lldb/trunk/packages/Python/lldbsuite/test/lang/c/struct_types/main.c @@ -29,6 +29,10 @@ //% self.expect("expression -- (pt.padding[0])", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["(char)", " = "]) //% self.expect("image lookup -t point_tag", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ['padding[]']) # Once rdar://problem/12566646 is fixed, this should display correctly + struct {} empty; + //% self.expect("frame variable empty", substrs = ["empty = {}"]) + //% self.expect("expression -- sizeof(empty)", substrs = ["= 0"]) + struct rect_tag { struct point_tag bottom_left; struct point_tag top_right; Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function_refs/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function_refs/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function_refs/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function_refs/TestFunctionRefs.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function_refs/TestFunctionRefs.py +++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function_refs/TestFunctionRefs.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals()) Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function_refs/main.cpp =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function_refs/main.cpp +++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function_refs/main.cpp @@ -0,0 +1,32 @@ +// This is plagiarized from lit/SymbolFile/NativePDB/function-types-builtin.cpp. +void nullary() {} + +template +void unary(Arg) { } + +template +void binary(A1, A2) { } + +int varargs(int, int, ...) { return 0; } + +auto &ref = unary; +auto &ref2 = unary; +auto &ref3 = varargs; +auto binp = &binary; +auto &binr = binary; +auto null = &nullary; +int main(int argc, char **argv) { +//% self.expect("target var ref", substrs=["(void (&)(bool))", "ref = 0x", +//% "&::ref = "]) +//% self.expect("target var ref2", +//% substrs=["(void (&)(volatile int *))", "ref2 = 0x"]) +//% self.expect("target var ref3", +//% substrs=["(int (&)(int, int, ...))", "ref3 = 0x"]) +//% self.expect("target var binp", +//% substrs=["(void (*)(int *, const int *))", "binp = 0x"]) +//% self.expect("target var binr", +//% substrs=["(void (&)(int *, const int *))", "binr = 0x"]) +//% self.expect("target var null", +//% substrs=["(void (*)())", "null = 0x"]) + return 0; +} Index: lldb/trunk/source/Core/Value.cpp =================================================================== --- lldb/trunk/source/Core/Value.cpp +++ lldb/trunk/source/Core/Value.cpp @@ -210,35 +210,31 @@ } uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) { - uint64_t byte_size = 0; - switch (m_context_type) { case eContextTypeRegisterInfo: // RegisterInfo * - if (GetRegisterInfo()) - byte_size = GetRegisterInfo()->byte_size; + if (GetRegisterInfo()) { + if (error_ptr) + error_ptr->Clear(); + return GetRegisterInfo()->byte_size; + } break; case eContextTypeInvalid: case eContextTypeLLDBType: // Type * case eContextTypeVariable: // Variable * { - const CompilerType &ast_type = GetCompilerType(); - if (ast_type.IsValid()) - if (llvm::Optional size = ast_type.GetByteSize( - exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr)) - byte_size = *size; - } break; - } - - if (error_ptr) { - if (byte_size == 0) { - if (error_ptr->Success()) - error_ptr->SetErrorString("Unable to determine byte size."); - } else { - error_ptr->Clear(); + auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; + if (llvm::Optional size = GetCompilerType().GetByteSize(scope)) { + if (error_ptr) + error_ptr->Clear(); + return *size; } + break; + } } - return byte_size; + if (error_ptr && error_ptr->Success()) + error_ptr->SetErrorString("Unable to determine byte size."); + return 0; } const CompilerType &Value::GetCompilerType() { @@ -519,6 +515,10 @@ if (error.Fail()) return error; + // No memory to read for zero-sized types. + if (byte_size == 0) + return error; + // Make sure we have enough room within "data", and if we don't make // something large enough that does if (!data.ValidOffsetForDataOfSize(data_offset, byte_size)) { Index: lldb/trunk/source/Symbol/ClangASTContext.cpp =================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp +++ lldb/trunk/source/Symbol/ClangASTContext.cpp @@ -5010,8 +5010,9 @@ // Exploring the type //---------------------------------------------------------------------- -uint64_t ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type, - ExecutionContextScope *exe_scope) { +Optional +ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) { if (GetCompleteType(type)) { clang::QualType qual_type(GetCanonicalQualType(type)); const clang::Type::TypeClass type_class = qual_type->getTypeClass(); @@ -5020,7 +5021,7 @@ if (GetCompleteType(type)) return getASTContext()->getTypeSize(qual_type); else - return 0; + return None; break; case clang::Type::ObjCInterface: @@ -5065,10 +5066,14 @@ return bit_size + getASTContext()->getTypeSize( getASTContext()->ObjCBuiltinClassTy); - return bit_size; + // Function types actually have a size of 0, that's not an error. + if (qual_type->isFunctionProtoType()) + return bit_size; + if (bit_size) + return bit_size; } } - return 0; + return None; } size_t ClangASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) {