steakhal updated this revision to Diff 433734. steakhal marked an inline comment as done. steakhal added a comment.
- host common implementation 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,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,60 +271,28 @@ } }; - // 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, void>> + : 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, void>> + : DefaultProgramStatePartialTraitImpl<T> {}; - static void *MakeVoidPtr(data_type d) { - return const_cast<void *>(d); - } - }; + // Partial specialization for non-const and const 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