[llvm-commits] [PATCH] Rewrite isa<> impl to match the cast<> impl (PR7952)

Eli Friedman eli.friedman at gmail.com
Sat Apr 16 00:18:21 PDT 2011


Attached rewrites isa<> so it uses the same logic as cast<> to figure
out the underlying type of the argument; in particular, this means
that it won't automatically dereference multi-level pointers.  My
knowledge of C++ templates is relatively weak, but this patch seems
correct.

The change to include/clang/AST/DeclBase.h in clang is necessary
because it specialized a template whose meaning has changed.

The rest of the changes are just making sure not to use isa<> on
multi-level pointers.

-Eli
-------------- next part --------------
Index: include/clang/AST/DeclBase.h
===================================================================
--- include/clang/AST/DeclBase.h	(revision 129634)
+++ include/clang/AST/DeclBase.h	(working copy)
@@ -1333,17 +1333,12 @@
 namespace llvm {
 
 /// isa<T>(DeclContext*)
-template<class ToTy>
-struct isa_impl_wrap<ToTy,
-                     const ::clang::DeclContext,const ::clang::DeclContext> {
+template <typename To>
+struct isa_impl<To, ::clang::DeclContext> {
   static bool doit(const ::clang::DeclContext &Val) {
-    return ToTy::classofKind(Val.getDeclKind());
+    return To::classofKind(Val.getDeclKind());
   }
 };
-template<class ToTy>
-struct isa_impl_wrap<ToTy, ::clang::DeclContext, ::clang::DeclContext>
-  : public isa_impl_wrap<ToTy,
-                      const ::clang::DeclContext,const ::clang::DeclContext> {};
 
 /// cast<T>(DeclContext*)
 template<class ToTy>
Index: lib/Frontend/CreateInvocationFromCommandLine.cpp
===================================================================
--- lib/Frontend/CreateInvocationFromCommandLine.cpp	(revision 129634)
+++ lib/Frontend/CreateInvocationFromCommandLine.cpp	(working copy)
@@ -65,7 +65,7 @@
   // We expect to get back exactly one command job, if we didn't something
   // failed.
   const driver::JobList &Jobs = C->getJobs();
-  if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
+  if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
     llvm::SmallString<256> Msg;
     llvm::raw_svector_ostream OS(Msg);
     C->PrintJob(OS, C->getJobs(), "; ", true);
Index: lib/CodeGen/CGStmt.cpp
===================================================================
--- lib/CodeGen/CGStmt.cpp	(revision 129634)
+++ lib/CodeGen/CGStmt.cpp	(working copy)
@@ -978,7 +978,7 @@
       // If we're looking for the case, just see if we can skip each of the
       // substatements.
       for (; Case && I != E; ++I) {
-        HadSkippedDecl |= isa<DeclStmt>(I);
+        HadSkippedDecl |= isa<DeclStmt>(*I);
         
         switch (CollectStatementsForCase(*I, Case, FoundCase, ResultStmts)) {
         case CSFC_Failure: return CSFC_Failure;
-------------- next part --------------
Index: lib/Transforms/Scalar/SCCP.cpp
===================================================================
--- lib/Transforms/Scalar/SCCP.cpp	(revision 129634)
+++ lib/Transforms/Scalar/SCCP.cpp	(working copy)
@@ -655,7 +655,7 @@
   
   // Just mark all destinations executable!
   // TODO: This could be improved if the operand is a [cast of a] BlockAddress.
-  if (isa<IndirectBrInst>(&TI))
+  if (isa<IndirectBrInst>(TI))
     return true;
   
 #ifndef NDEBUG
Index: include/llvm/Support/Casting.h
===================================================================
--- include/llvm/Support/Casting.h	(revision 129634)
+++ include/llvm/Support/Casting.h	(working copy)
@@ -23,8 +23,6 @@
 //                          isa<x> Support Templates
 //===----------------------------------------------------------------------===//
 
-template<typename FromCl> struct isa_impl_cl;
-
 // Define a template that can be specialized by smart pointers to reflect the
 // fact that they are automatically dereferenced, and are not involved with the
 // template selection process...  the default implementation is a noop.
@@ -43,12 +41,9 @@
   }
 };
 
-
-// isa<X> - Return true if the parameter to the template is an instance of the
-// template type argument.  Used like this:
-//
-//  if (isa<Type*>(myVal)) { ... }
-//
+// The core of the implementation of isa<X> is here; To and From should be
+// the names of classes.  This template can be specialized to customize the
+// implementation of isa<> without rewriting it from scratch.
 template <typename To, typename From>
 struct isa_impl {
   static inline bool doit(const From &Val) {
@@ -56,66 +51,63 @@
   }
 };
 
-template<typename To, typename From, typename SimpleType>
-struct isa_impl_wrap {
-  // When From != SimplifiedType, we can simplify the type some more by using
-  // the simplify_type template.
-  static bool doit(const From &Val) {
-    return isa_impl_cl<const SimpleType>::template
-                    isa<To>(simplify_type<const From>::getSimplifiedValue(Val));
+template <typename To, typename From> struct isa_impl_cl {
+  static inline bool doit(const From &Val) {
+    return isa_impl<To, From>::doit(Val);
   }
 };
 
-template<typename To, typename FromTy>
-struct isa_impl_wrap<To, const FromTy, const FromTy> {
-  // When From == SimpleType, we are as simple as we are going to get.
-  static bool doit(const FromTy &Val) {
-    return isa_impl<To,FromTy>::doit(Val);
+template <typename To, typename From> struct isa_impl_cl<To, const From> {
+  static inline bool doit(const From &Val) {
+    return isa_impl<To, From>::doit(Val);
   }
 };
 
-// isa_impl_cl - Use class partial specialization to transform types to a single
-// canonical form for isa_impl.
-//
-template<typename FromCl>
-struct isa_impl_cl {
-  template<class ToCl>
-  static bool isa(const FromCl &Val) {
-    return isa_impl_wrap<ToCl,const FromCl,
-                   typename simplify_type<const FromCl>::SimpleType>::doit(Val);
+template <typename To, typename From> struct isa_impl_cl<To, From*> {
+  static inline bool doit(const From *Val) {
+    return isa_impl<To, From>::doit(*Val);
   }
 };
 
-// Specialization used to strip const qualifiers off of the FromCl type...
-template<typename FromCl>
-struct isa_impl_cl<const FromCl> {
-  template<class ToCl>
-  static bool isa(const FromCl &Val) {
-    return isa_impl_cl<FromCl>::template isa<ToCl>(Val);
+template <typename To, typename From> struct isa_impl_cl<To, const From*> {
+  static inline bool doit(const From *Val) {
+    return isa_impl<To, From>::doit(*Val);
   }
 };
 
-// Define pointer traits in terms of base traits...
-template<class FromCl>
-struct isa_impl_cl<FromCl*> {
-  template<class ToCl>
-  static bool isa(FromCl *Val) {
-    return isa_impl_cl<FromCl>::template isa<ToCl>(*Val);
+template <typename To, typename From> struct isa_impl_cl<To, const From*const> {
+  static inline bool doit(const From *Val) {
+    return isa_impl<To, From>::doit(*Val);
   }
 };
 
-// Define reference traits in terms of base traits...
-template<class FromCl>
-struct isa_impl_cl<FromCl&> {
-  template<class ToCl>
-  static bool isa(FromCl &Val) {
-    return isa_impl_cl<FromCl>::template isa<ToCl>(&Val);
+template<typename To, typename From, typename SimpleFrom>
+struct isa_impl_wrap {
+  // When From != SimplifiedType, we can simplify the type some more by using
+  // the simplify_type template.
+  static bool doit(const From &Val) {
+    return isa_impl_wrap<To, SimpleFrom,
+      typename simplify_type<SimpleFrom>::SimpleType>::doit(
+                          simplify_type<From>::getSimplifiedValue(Val));
   }
 };
 
+template<typename To, typename FromTy>
+struct isa_impl_wrap<To, FromTy, FromTy> {
+  // When From == SimpleType, we are as simple as we are going to get.
+  static bool doit(const FromTy &Val) {
+    return isa_impl_cl<To,FromTy>::doit(Val);
+  }
+};
+
+// isa<X> - Return true if the parameter to the template is an instance of the
+// template type argument.  Used like this:
+//
+//  if (isa<Type>(myVal)) { ... }
+//
 template <class X, class Y>
 inline bool isa(const Y &Val) {
-  return isa_impl_cl<Y>::template isa<X>(Val);
+  return isa_impl_wrap<X, Y, typename simplify_type<Y>::SimpleType>::doit(Val);
 }
 
 //===----------------------------------------------------------------------===//


More information about the llvm-commits mailing list