Add a verification mechanism to CompilerType.
authorAdrian Prantl <aprantl@apple.com>
Wed, 11 Mar 2020 17:44:15 +0000 (10:44 -0700)
committerAdrian Prantl <aprantl@apple.com>
Wed, 11 Mar 2020 19:43:32 +0000 (12:43 -0700)
Badly-written code can combine an unrelated TypeSystem and opaque type
pointer into a CompilerType. This is particularly an issue in
swift-lldb. This patch adds an assertion mechanism that catches these
kinds of mistakes early. Because this is an assertion-only code path
there is not cost for release builds.

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

lldb/include/lldb/Symbol/CompilerType.h
lldb/include/lldb/Symbol/TypeSystem.h
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
lldb/source/Symbol/CompilerType.cpp
lldb/source/Symbol/TypeSystem.cpp

index 0d536e0..0d1b00a 100644 (file)
@@ -39,7 +39,9 @@ public:
   ///
   /// \see lldb_private::TypeSystemClang::GetType(clang::QualType)
   CompilerType(TypeSystem *type_system, lldb::opaque_compiler_type_t type)
-      : m_type(type), m_type_system(type_system) {}
+      : m_type(type), m_type_system(type_system) {
+    assert(Verify() && "verification failed");
+  }
 
   CompilerType(const CompilerType &rhs)
       : m_type(rhs.m_type), m_type_system(rhs.m_type_system) {}
@@ -380,6 +382,13 @@ public:
   }
 
 private:
+#ifndef NDEBUG
+  /// If the type is valid, ask the TypeSystem to verify the integrity
+  /// of the type to catch CompilerTypes that mix and match invalid
+  /// TypeSystem/Opaque type pairs.
+  bool Verify() const;
+#endif
+
   lldb::opaque_compiler_type_t m_type = nullptr;
   TypeSystem *m_type_system = nullptr;
 };
index 37c87a4..a84b9a1 100644 (file)
@@ -129,6 +129,11 @@ public:
                                               void *other_opaque_decl_ctx) = 0;
 
   // Tests
+#ifndef NDEBUG
+  /// Verify the integrity of the type to catch CompilerTypes that mix
+  /// and match invalid TypeSystem/Opaque type pairs.
+  virtual bool Verify(lldb::opaque_compiler_type_t type) = 0;
+#endif
 
   virtual bool IsArrayType(lldb::opaque_compiler_type_t type,
                            CompilerType *element_type, uint64_t *size,
index 47f1a85..42655ad 100644 (file)
@@ -2532,6 +2532,12 @@ ConvertAccessTypeToObjCIvarAccessControl(AccessType access) {
 
 // Tests
 
+#ifndef NDEBUG
+bool TypeSystemClang::Verify(lldb::opaque_compiler_type_t type) {
+  return !type || llvm::isa<clang::Type>(GetQualType(type).getTypePtr());
+}
+#endif
+
 bool TypeSystemClang::IsAggregateType(lldb::opaque_compiler_type_t type) {
   clang::QualType qual_type(RemoveWrappingTypes(GetCanonicalQualType(type)));
 
index 75e749f..e22635d 100644 (file)
@@ -495,6 +495,10 @@ public:
 
   // Tests
 
+#ifndef NDEBUG
+  bool Verify(lldb::opaque_compiler_type_t type) override;
+#endif
+  
   bool IsArrayType(lldb::opaque_compiler_type_t type,
                    CompilerType *element_type, uint64_t *size,
                    bool *is_incomplete) override;
index 1507f2c..6c15098 100644 (file)
@@ -865,6 +865,12 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data,
   return false;
 }
 
+#ifndef NDEBUG
+bool CompilerType::Verify() const {
+  return !IsValid() || m_type_system->Verify(m_type);
+}
+#endif
+
 bool lldb_private::operator==(const lldb_private::CompilerType &lhs,
                               const lldb_private::CompilerType &rhs) {
   return lhs.GetTypeSystem() == rhs.GetTypeSystem() &&
index b0131e9..fd5b961 100644 (file)
@@ -70,6 +70,10 @@ lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
   return CreateInstanceHelper(language, nullptr, target);
 }
 
+#ifndef NDEBUG
+bool TypeSystem::Verify(lldb::opaque_compiler_type_t type) { return true; }
+#endif
+
 bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) {
   return false;
 }