From 3ee9cc295aaa4d652a9cd4e48f997ce974ac7ada Mon Sep 17 00:00:00 2001
From: Adrian Prantl <aprantl@apple.com>
Date: Fri, 22 Mar 2013 13:34:39 -0700
Subject: [PATCH] Introduce a createVoidType() function to DI Builder.
 According to section 5.2 of the DWARF4 standard, the void type should be
 represented as an unspecified type with the name "void".

Fix for rdar://problem/13291085
---
 include/llvm/DIBuilder.h |  5 ++++-
 lib/IR/DIBuilder.cpp     | 23 ++++++++++++++++++++++-
 test/DebugInfo/void.ll   | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 2 deletions(-)
 create mode 100644 test/DebugInfo/void.ll

diff --git a/include/llvm/DIBuilder.h b/include/llvm/DIBuilder.h
index de6c38f..4278b10 100644
--- a/include/llvm/DIBuilder.h
+++ b/include/llvm/DIBuilder.h
@@ -105,9 +105,12 @@ namespace llvm {
     /// createEnumerator - Create a single enumerator value.
     DIEnumerator createEnumerator(StringRef Name, uint64_t Val);
 
-    /// createNullPtrType - Create C++0x nullptr type.
+    /// createNullPtrType - Create the C++0x nullptr type.
     DIType createNullPtrType(StringRef Name);
 
+    /// createVoidType - Create the C-style void type.
+    DIType createVoidType(StringRef Name);
+
     /// createBasicType - Create debugging information entry for a basic 
     /// type.
     /// @param Name        Type name.
diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp
index a97b740..25ce8b2 100644
--- a/lib/IR/DIBuilder.cpp
+++ b/lib/IR/DIBuilder.cpp
@@ -143,7 +143,7 @@ DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) {
   return DIEnumerator(MDNode::get(VMContext, Elts));
 }
 
-/// createNullPtrType - Create C++0x nullptr type.
+/// createNullPtrType - Create the C++0x nullptr type.
 DIType DIBuilder::createNullPtrType(StringRef Name) {
   assert(!Name.empty() && "Unable to create type without name");
   // nullptr is encoded in DIBasicType format. Line number, filename,
@@ -163,6 +163,27 @@ DIType DIBuilder::createNullPtrType(StringRef Name) {
   return DIType(MDNode::get(VMContext, Elts));
 }
 
+/// createVoidType - Create the C-style void type.
+/// According to section 5.2 of the DWARF4 standard, the void type
+/// should be represented as an unspecified type with the name "void".
+DIType DIBuilder::createVoidType(StringRef Name) {
+  assert(!Name.empty() && "Unable to create type without name");
+  Value *Elts[] = {
+    GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_type),
+    NULL, // Filename
+    NULL, //TheCU,
+    MDString::get(VMContext, Name),
+    ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
+    ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
+    ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
+    ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
+    ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags;
+    ConstantInt::get(Type::getInt32Ty(VMContext), 0)  // Encoding
+  };
+  return DIType(MDNode::get(VMContext, Elts));
+}
+
+
 /// createBasicType - Create debugging information entry for a basic
 /// type, e.g 'char'.
 DIBasicType
diff --git a/test/DebugInfo/void.ll b/test/DebugInfo/void.ll
new file mode 100644
index 0000000..6bdd2de
--- /dev/null
+++ b/test/DebugInfo/void.ll
@@ -0,0 +1,35 @@
+; RUN: llc -mtriple=x86_64-apple-macosx10.8.0 < %s -filetype=obj | llvm-dwarfdump - | FileCheck %s
+; ModuleID = 'void.c'
+; Test that we generate a unique unspecified type named "void".
+;
+; CHECK:      [[VOID:.*]]: DW_TAG_unspecified_type
+; CHECK-NEXT:   AT_name {{.*}} "void"
+; CHECK:      DW_TAG_pointer_type
+; CHECK-NEXT:   DW_AT_type {{.*}}{[[VOID]]}
+; CHECK:      [[CONSTVOID:.*]]: DW_TAG_const_type
+; CHECK-NEXT:   DW_AT_type {{.*}}{[[VOID]]}
+; CHECK:      DW_TAG_pointer_type [3]
+; CHECK-NEXT:   DW_AT_type {{.*}}{[[CONSTVOID]]}
+
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.8.0"
+
+@x = common global i8* null, align 8
+@y = common global i8* null, align 8
+@z = common global i8* null, align 8
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.3 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !2, metadata !3, metadata !""} ; [ DW_TAG_compile_unit ] [void.c] [DW_LANG_C99]
+!1 = metadata !{metadata !"void.c", metadata !""}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4, metadata !8, metadata !9}
+!4 = metadata !{i32 786484, i32 0, null, metadata !"x", metadata !"x", metadata !"", metadata !5, i32 1, metadata !6, i32 0, i32 1, i8** @x, null} ; [ DW_TAG_variable ] [x] [line 1] [def]
+!5 = metadata !{i32 786473, metadata !1}          ; [ DW_TAG_file_type ] [void.c]
+!6 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !7} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from void]
+!7 = metadata !{i32 786491, null, null, metadata !"void", i32 0, i64 0, i64 0, i64 0, i32 0, i32 0} ; [ DW_TAG_unspecified_type ] [void] [line 0, size 0, align 0, offset 0]
+!8 = metadata !{i32 786484, i32 0, null, metadata !"y", metadata !"y", metadata !"", metadata !5, i32 2, metadata !6, i32 0, i32 1, i8** @y, null} ; [ DW_TAG_variable ] [y] [line 2] [def]
+!9 = metadata !{i32 786484, i32 0, null, metadata !"z", metadata !"z", metadata !"", metadata !5, i32 3, metadata !10, i32 0, i32 1, i8** @z, null} ; [ DW_TAG_variable ] [z] [line 3] [def]
+!10 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !11} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from ]
+!11 = metadata !{i32 786470, null, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, metadata !7} ; [ DW_TAG_const_type ] [line 0, size 0, align 0, offset 0] [from void]
-- 
1.8.1.5 (Apple Git-44)

