steakhal created this revision.
steakhal added reviewers: NoQ, martong, balazske, ASDenysPetrov.
Herald added subscribers: manas, dkrupp, donat.nagy, Szelethus,
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun.
Herald added a reviewer: Szelethus.
Herald added a project: All.
steakhal requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Also, specialize it for enums.
Repository:
rG LLVM Github Monorepo
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,33 @@
#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 = /*For SFINAE*/ 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,58 +271,43 @@
}
};
- // 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;
- }
- };
-
- // Partial specialization for unsigned.
- template <> struct ProgramStatePartialTrait<unsigned> {
- using data_type = unsigned;
+ // Partial specialization for integral types.
+ template <typename T>
+ struct ProgramStatePartialTrait<
+ T, std::enable_if_t<std::is_integral<T>::value, void>> {
+ using data_type = T;
static data_type MakeData(void *const *p) {
- return p ? (data_type) (uintptr_t) *p
- : data_type();
+ return p ? (data_type)(uintptr_t)*p : data_type();
}
- static void *MakeVoidPtr(data_type d) {
- return (void *) (uintptr_t) d;
- }
+ static void *MakeVoidPtr(data_type d) { return (void *)(uintptr_t)d; }
};
- // Partial specialization for void*.
- template <> struct ProgramStatePartialTrait<void *> {
- using data_type = void *;
+ // Partial specialization for enums.
+ template <typename T>
+ struct ProgramStatePartialTrait<
+ T, std::enable_if_t<std::is_enum<T>::value, void>> {
+ using data_type = T;
static data_type MakeData(void *const *p) {
- return p ? *p
- : data_type();
+ return p ? (data_type)(uintptr_t)*p : data_type();
}
- static void *MakeVoidPtr(data_type d) {
- return d;
- }
+ static void *MakeVoidPtr(data_type d) { return (void *)(uintptr_t)d; }
};
- // Partial specialization for const void *.
- template <> struct ProgramStatePartialTrait<const void *> {
- using data_type = const void *;
+ // Partial specialization for non-const and const pointers.
+ template <typename T> struct ProgramStatePartialTrait<T *, void> {
+ using data_type = T *;
static data_type MakeData(void *const *p) {
- return p ? *p : data_type();
+ return p ? (data_type)(uintptr_t)*p : nullptr;
}
static void *MakeVoidPtr(data_type d) {
- return const_cast<void *>(d);
+ return static_cast<void *>(
+ const_cast<typename std::remove_const<T>::type *>(d));
}
};
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits