Devirtualize Decl::getCanonicalDecl().


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125735 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index e0ffa62..b762be6 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -430,7 +430,7 @@
     getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D);
   }
 
-  virtual NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); }
+  NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); }
   const NamespaceDecl *getCanonicalDecl() const { 
     return getOriginalNamespace(); 
   }
@@ -779,7 +779,7 @@
     return getKind() != Decl::ParmVar && getDeclContext()->isRecord();
   }
 
-  virtual VarDecl *getCanonicalDecl();
+  VarDecl *getCanonicalDecl();
   const VarDecl *getCanonicalDecl() const {
     return const_cast<VarDecl*>(this)->getCanonicalDecl();
   }
@@ -1467,8 +1467,8 @@
 
   void setPreviousDeclaration(FunctionDecl * PrevDecl);
 
-  virtual const FunctionDecl *getCanonicalDecl() const;
-  virtual FunctionDecl *getCanonicalDecl();
+  const FunctionDecl *getCanonicalDecl() const;
+  FunctionDecl *getCanonicalDecl();
 
   unsigned getBuiltinID() const;
 
@@ -2073,7 +2073,7 @@
   SourceLocation getOuterLocStart() const;
   virtual SourceRange getSourceRange() const;
 
-  virtual TagDecl* getCanonicalDecl();
+  TagDecl* getCanonicalDecl();
   const TagDecl* getCanonicalDecl() const {
     return const_cast<TagDecl*>(this)->getCanonicalDecl();
   }
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 1407dad..2ce43cb 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -477,7 +477,7 @@
   bool isDefinedOutsideFunctionOrMethod() const;
 
   /// \brief Retrieves the "canonical" declaration of the given declaration.
-  virtual Decl *getCanonicalDecl() { return this; }
+  Decl *getCanonicalDecl();
   const Decl *getCanonicalDecl() const {
     return const_cast<Decl*>(this)->getCanonicalDecl();
   }
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index d11ee8f..61f71e9 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -472,10 +472,10 @@
   typedef std::reverse_iterator<base_class_const_iterator>
     reverse_base_class_const_iterator;
 
-  virtual CXXRecordDecl *getCanonicalDecl() {
+  CXXRecordDecl *getCanonicalDecl() {
     return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
   }
-  virtual const CXXRecordDecl *getCanonicalDecl() const {
+  const CXXRecordDecl *getCanonicalDecl() const {
     return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
   }
   
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 81f5d39..df89b6f 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -198,7 +198,7 @@
                                 ImplementationControl impControl = None,
                                 unsigned numSelectorArgs = 0);
 
-  virtual ObjCMethodDecl *getCanonicalDecl();
+  ObjCMethodDecl *getCanonicalDecl();
   const ObjCMethodDecl *getCanonicalDecl() const {
     return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl();
   }
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index dfc5a6a..d8b7c9b 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -143,6 +143,29 @@
   return true;
 }
 
+namespace {
+  template<typename Class, typename Result>
+  inline Result *getSpecificCanonicalDecl(Decl *D, Result *(Class::*Get)()) {
+    return (llvm::cast<Class>(D)->*Get)();
+  }
+  
+  inline Decl *getSpecificCanonicalDecl(Decl *D, Decl *(Decl::*)()) {
+    // No specific implementation.
+    return D;
+  }
+}
+
+Decl *Decl::getCanonicalDecl() {
+  switch (getKind()) {
+#define ABSTRACT_DECL(Type)
+#define DECL(Type, Base) \
+    case Type:           \
+      return getSpecificCanonicalDecl(this, &Type##Decl::getCanonicalDecl);
+#include "clang/AST/DeclNodes.inc"
+  }
+  return this;
+  
+}
 
 //===----------------------------------------------------------------------===//
 // PrettyStackTraceDecl Implementation