[SymbolFilePDB] Add support for CVR pointer type qualifier
authorAaron Smith <aaron.smith@microsoft.com>
Wed, 7 Mar 2018 00:39:25 +0000 (00:39 +0000)
committerAaron Smith <aaron.smith@microsoft.com>
Wed, 7 Mar 2018 00:39:25 +0000 (00:39 +0000)
Summary:
- Complete element type of PDBSymbolTypeArray.

- Add a test to check types of multi-dimensional array and pointers with CVR.

Reviewers: zturner, rnk, lldb-commits

Reviewed By: zturner

Subscribers: llvm-commits

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

llvm-svn: 326859

lldb/lit/SymbolFile/PDB/Inputs/TypeQualsTest.cpp [new file with mode: 0644]
lldb/lit/SymbolFile/PDB/type-quals.test [new file with mode: 0644]
lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp

diff --git a/lldb/lit/SymbolFile/PDB/Inputs/TypeQualsTest.cpp b/lldb/lit/SymbolFile/PDB/Inputs/TypeQualsTest.cpp
new file mode 100644 (file)
index 0000000..bedafcd
--- /dev/null
@@ -0,0 +1,46 @@
+// Rank > 0 array
+typedef volatile int* RankNArray[10][100];
+RankNArray ArrayVar;
+
+typedef int __unaligned *UnalignedTypedef;
+UnalignedTypedef UnVar;
+
+typedef long* __restrict RestrictTypedef;
+RestrictTypedef RestrictVar;
+
+void Func1(const int* a, int const* b, const int ** const c, const int* const* d) {
+  return;
+}
+
+void Func2(volatile int* a, int volatile* b) {
+ return;
+}
+
+void Func3(int*& a, int& b, const int&c, int&& d) {
+  return;
+}
+
+void Func4(int* __unaligned a, __unaligned int* b) {
+  return;
+}
+
+void Func5(int a, int* __restrict b, int& __restrict c) {
+  return;
+}
+
+void Func6(const volatile int* __restrict b) {
+  return;
+}
+
+// LValue
+typedef int& IntRef;
+int x = 0;
+IntRef IVar = x;
+
+// RValue
+typedef int&& IIRef;
+IIRef IIVar = int(1);
+
+int main() {
+  return 0;
+}
diff --git a/lldb/lit/SymbolFile/PDB/type-quals.test b/lldb/lit/SymbolFile/PDB/type-quals.test
new file mode 100644 (file)
index 0000000..fbe10c0
--- /dev/null
@@ -0,0 +1,39 @@
+REQUIRES: windows
+RUN: clang-cl -m32 /Z7 /c /GS- %S/Inputs/TypeQualsTest.cpp /o %T/TypeQualsTest.cpp.obj
+RUN: link %T/TypeQualsTest.cpp.obj /DEBUG /nodefaultlib /ENTRY:main /OUT:%T/TypeQualsTest.cpp.exe
+RUN: lldb-test symbols %T/TypeQualsTest.cpp.exe | FileCheck %s
+
+CHECK: Module [[MOD:.*]]
+CHECK-DAG: {{^[0-9A-F]+}}: SymbolVendor ([[MOD]])
+CHECK:      Type{{.*}} , name = "const int", size = 4, compiler_type = {{.*}} const int
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} const int *
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} const int **const
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} const int *const
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} const int *const *
+CHECK:      Type{{.*}} , name = "Func1", {{.*}}, compiler_type = {{.*}} void (const int *, const int *, const int **const, const int *const *)
+
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} volatile int *
+CHECK:      Type{{.*}} , name = "Func2", {{.*}}, compiler_type = {{.*}} void (volatile int *, volatile int *)
+
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} int *
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} int *&
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} int &
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} const int &
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} int &&
+CHECK:      Type{{.*}} , name = "Func3", {{.*}}, compiler_type = {{.*}} void (int *&, int &, const int &, int &&)
+
+// FIXME: __unaligned is not supported.
+CHECK:      Type{{.*}} , name = "Func4", {{.*}}, compiler_type = {{.*}} void (int *, int *)
+
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} int *__restrict
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} int &__restrict
+CHECK:      Type{{.*}} , name = "Func5", {{.*}}, compiler_type = {{.*}} void (int, int *__restrict, int &__restrict)
+
+CHECK:      Type{{.*}} , name = "Func6", {{.*}}, compiler_type = {{.*}} void (const volatile int *__restrict)
+
+CHECK:      Type{{.*}} , size = 400, compiler_type = {{.*}} volatile int *[100]
+CHECK:      Type{{.*}} , size = 4000, compiler_type = {{.*}} volatile int *[10][100]
+
+CHECK:      Type{{.*}} , size = 4, compiler_type = {{.*}} long *__restrict
+
+CHECK-DAG: {{^[0-9A-F]+}}:   CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\TypeQualsTest.cpp'
index 4a73649deb2caab74a6df01cea751c96c36958d6..9761baea23147ba91a34d04758e1b5b8e15e2506 100644 (file)
@@ -292,6 +292,9 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
         m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID());
     CompilerType ast_typedef =
         m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx);
+    if (!ast_typedef)
+      return nullptr;
+
     return std::make_shared<lldb_private::Type>(
         type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
         bytes, nullptr, target_type->GetID(),
@@ -365,20 +368,35 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
     auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type);
     assert(array_type);
     uint32_t num_elements = array_type->getCount();
-    uint32_t element_uid = array_type->getElementType()->getSymIndexId();
+    uint32_t element_uid = array_type->getElementTypeId();
     uint32_t bytes = array_type->getLength();
 
+    // If array rank > 0, PDB gives the element type at N=0. So element type
+    // will parsed in the order N=0, N=1,..., N=rank sequentially.
     lldb_private::Type *element_type =
         m_ast.GetSymbolFile()->ResolveTypeUID(element_uid);
     if (!element_type)
       return nullptr;
-    CompilerType element_ast_type = element_type->GetFullCompilerType();
+
+    CompilerType element_ast_type = element_type->GetForwardCompilerType();
+    // If element type is UDT, it needs to be complete.
+    if (ClangASTContext::IsCXXClassType(element_ast_type) &&
+        element_ast_type.GetCompleteType() == false) {
+      if (ClangASTContext::StartTagDeclarationDefinition(element_ast_type)) {
+        ClangASTContext::CompleteTagDeclarationDefinition(element_ast_type);
+      } else {
+        // We are not able to start defintion.
+        return nullptr;
+      }
+    }
     CompilerType array_ast_type =
-        m_ast.CreateArrayType(element_ast_type, num_elements, false);
-    return std::make_shared<lldb_private::Type>(
+        m_ast.CreateArrayType(element_ast_type, num_elements, /*is_gnu_vector*/false);
+    TypeSP type_sp = std::make_shared<lldb_private::Type>(
         array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
         bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
         decl, array_ast_type, lldb_private::Type::eResolveStateFull);
+    type_sp->SetEncodingType(element_type);
+    return type_sp;
   } break;
   case PDB_SymType::BuiltinType: {
     auto *builtin_type = llvm::dyn_cast<PDBSymbolTypeBuiltin>(&type);
@@ -392,20 +410,17 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
     CompilerType builtin_ast_type = GetBuiltinTypeForPDBEncodingAndBitSize(
         &m_ast, builtin_type, encoding, bytes * 8);
 
-    Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
-    if (builtin_type->isConstType()) {
-      encoding_data_type = Type::eEncodingIsConstUID;
+    if (builtin_type->isConstType())
       builtin_ast_type = builtin_ast_type.AddConstModifier();
-    }
-    if (builtin_type->isVolatileType()) {
-      encoding_data_type = Type::eEncodingIsVolatileUID;
+
+    if (builtin_type->isVolatileType())
       builtin_ast_type = builtin_ast_type.AddVolatileModifier();
-    }
+
     auto type_name = GetPDBBuiltinTypeName(builtin_type, builtin_ast_type);
 
     return std::make_shared<lldb_private::Type>(
         builtin_type->getSymIndexId(), m_ast.GetSymbolFile(), type_name,
-        bytes, nullptr, LLDB_INVALID_UID, encoding_data_type,
+        bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
         decl, builtin_ast_type, lldb_private::Type::eResolveStateFull);
   } break;
   case PDB_SymType::PointerType: {
@@ -417,18 +432,27 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
       return nullptr;
 
     CompilerType pointer_ast_type;
-    Type::EncodingDataType encoding_data_type = Type::eEncodingIsPointerUID;
-    if (pointer_type->isReference()) {
-      encoding_data_type = Type::eEncodingIsLValueReferenceUID;
-      pointer_ast_type =
-          pointee_type->GetFullCompilerType().GetLValueReferenceType();
-    } else
-      pointer_ast_type = pointee_type->GetFullCompilerType().GetPointerType();
+    pointer_ast_type = pointee_type->GetFullCompilerType();
+    if (pointer_type->isReference())
+      pointer_ast_type = pointer_ast_type.GetLValueReferenceType();
+    else if (pointer_type->getRawSymbol().isRValueReference())
+      pointer_ast_type = pointer_ast_type.GetRValueReferenceType();
+    else
+      pointer_ast_type = pointer_ast_type.GetPointerType();
+
+    if (pointer_type->isConstType())
+      pointer_ast_type = pointer_ast_type.AddConstModifier();
+
+    if (pointer_type->isVolatileType())
+      pointer_ast_type = pointer_ast_type.AddVolatileModifier();
+
+    if (pointer_type->getRawSymbol().isRestrictedType())
+      pointer_ast_type = pointer_ast_type.AddRestrictModifier();
 
     return std::make_shared<lldb_private::Type>(
         pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
         pointer_type->getLength(), nullptr, LLDB_INVALID_UID,
-        encoding_data_type, decl, pointer_ast_type,
+        lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type,
         lldb_private::Type::eResolveStateFull);
   } break;
   default: break;