This revision was automatically updated to reflect the committed changes.
steakhal marked an inline comment as done.
Closed by commit rG33ca5a447e7f: [analyzer][NFC] Add partial specializations 
for ProgramStateTraits (authored by steakhal).

Changed prior to commit:
  https://reviews.llvm.org/D126801?vs=433734&id=433799#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126801/new/

https://reviews.llvm.org/D126801

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
  clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp

Index: clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/cert/InvalidPtrChecker.cpp
@@ -82,9 +82,7 @@
 REGISTER_SET_WITH_PROGRAMSTATE(InvalidMemoryRegions, const MemRegion *)
 
 // Stores the region of the environment pointer of 'main' (if present).
-// Note: This pointer has type 'const MemRegion *', however the trait is only
-// specialized to 'const void*' and 'void*'
-REGISTER_TRAIT_WITH_PROGRAMSTATE(EnvPtrRegion, const void *)
+REGISTER_TRAIT_WITH_PROGRAMSTATE(EnvPtrRegion, const MemRegion *)
 
 // Stores key-value pairs, where key is function declaration and value is
 // pointer to memory region returned by previous call of this function
@@ -95,11 +93,9 @@
                                              CheckerContext &C) const {
   StringRef FunctionName = Call.getCalleeIdentifier()->getName();
   ProgramStateRef State = C.getState();
-  const auto *Reg = State->get<EnvPtrRegion>();
-  if (!Reg)
+  const MemRegion *SymbolicEnvPtrRegion = State->get<EnvPtrRegion>();
+  if (!SymbolicEnvPtrRegion)
     return;
-  const auto *SymbolicEnvPtrRegion =
-      reinterpret_cast<const MemRegion *>(const_cast<const void *>(Reg));
 
   State = State->add<InvalidMemoryRegions>(SymbolicEnvPtrRegion);
 
@@ -245,9 +241,7 @@
 
   // Save the memory region pointed by the environment pointer parameter of
   // 'main'.
-  State = State->set<EnvPtrRegion>(
-      reinterpret_cast<void *>(const_cast<MemRegion *>(EnvpReg)));
-  C.addTransition(State);
+  C.addTransition(State->set<EnvPtrRegion>(EnvpReg));
 }
 
 // Check if invalidated region is being dereferenced.
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
@@ -21,29 +21,32 @@
 #include "llvm/ADT/ImmutableSet.h"
 #include "llvm/Support/Allocator.h"
 #include <cstdint>
+#include <type_traits>
 
 namespace clang {
 namespace ento {
 
-  template <typename T> struct ProgramStatePartialTrait;
-
-  /// Declares a program state trait for type \p Type called \p Name, and
-  /// introduce a type named \c NameTy.
-  /// The macro should not be used inside namespaces.
-  #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
-    namespace { \
-      class Name {}; \
-      using Name ## Ty = Type; \
-    } \
-    namespace clang { \
-    namespace ento { \
-      template <> \
-      struct ProgramStateTrait<Name> \
-        : public ProgramStatePartialTrait<Name ## Ty> { \
-        static void *GDMIndex() { static int Index; return &Index; } \
-      }; \
-    } \
-    }
+template <typename T, typename Enable = void> struct ProgramStatePartialTrait;
+
+/// Declares a program state trait for type \p Type called \p Name, and
+/// introduce a type named \c NameTy.
+/// The macro should not be used inside namespaces.
+#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)                           \
+  namespace {                                                                  \
+  class Name {};                                                               \
+  using Name##Ty = Type;                                                       \
+  }                                                                            \
+  namespace clang {                                                            \
+  namespace ento {                                                             \
+  template <>                                                                  \
+  struct ProgramStateTrait<Name> : public ProgramStatePartialTrait<Name##Ty> { \
+    static void *GDMIndex() {                                                  \
+      static int Index;                                                        \
+      return &Index;                                                           \
+    }                                                                          \
+  };                                                                           \
+  }                                                                            \
+  }
 
   /// Declares a factory for objects of type \p Type in the program state
   /// manager. The type must provide a ::Factory sub-class. Commonly used for
@@ -267,60 +270,27 @@
     }
   };
 
-  // Partial specialization for bool.
-  template <> struct ProgramStatePartialTrait<bool> {
-    using data_type = bool;
-
-    static data_type MakeData(void *const *p) {
-      return p ? (data_type) (uintptr_t) *p
-               : data_type();
-    }
-
-    static void *MakeVoidPtr(data_type d) {
-      return (void *) (uintptr_t) d;
-    }
+  template <typename T> struct DefaultProgramStatePartialTraitImpl {
+    using data_type = T;
+    static T MakeData(void *const *P) { return P ? (T)(uintptr_t)*P : T{}; }
+    static void *MakeVoidPtr(T D) { return (void *)(uintptr_t)D; }
   };
 
-  // Partial specialization for unsigned.
-  template <> struct ProgramStatePartialTrait<unsigned> {
-    using data_type = unsigned;
-
-    static data_type MakeData(void *const *p) {
-      return p ? (data_type) (uintptr_t) *p
-               : data_type();
-    }
-
-    static void *MakeVoidPtr(data_type d) {
-      return (void *) (uintptr_t) d;
-    }
-  };
-
-  // Partial specialization for void*.
-  template <> struct ProgramStatePartialTrait<void *> {
-    using data_type = void *;
-
-    static data_type MakeData(void *const *p) {
-      return p ? *p
-               : data_type();
-    }
-
-    static void *MakeVoidPtr(data_type d) {
-      return d;
-    }
-  };
-
-  // Partial specialization for const void *.
-  template <> struct ProgramStatePartialTrait<const void *> {
-    using data_type = const void *;
+  // Partial specialization for integral types.
+  template <typename T>
+  struct ProgramStatePartialTrait<T,
+                                  std::enable_if_t<std::is_integral<T>::value>>
+      : DefaultProgramStatePartialTraitImpl<T> {};
 
-    static data_type MakeData(void *const *p) {
-      return p ? *p : data_type();
-    }
+  // Partial specialization for enums.
+  template <typename T>
+  struct ProgramStatePartialTrait<T, std::enable_if_t<std::is_enum<T>::value>>
+      : DefaultProgramStatePartialTraitImpl<T> {};
 
-    static void *MakeVoidPtr(data_type d) {
-      return const_cast<void *>(d);
-    }
-  };
+  // Partial specialization for pointers.
+  template <typename T>
+  struct ProgramStatePartialTrait<T *, void>
+      : DefaultProgramStatePartialTraitImpl<T *> {};
 
 } // namespace ento
 } // namespace clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to