diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index e0ffa627ac21..b762be601e63 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -430,7 +430,7 @@ public: getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D); } - virtual NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); } + NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); } const NamespaceDecl *getCanonicalDecl() const { return getOriginalNamespace(); } @@ -779,7 +779,7 @@ public: return getKind() != Decl::ParmVar && getDeclContext()->isRecord(); } - virtual VarDecl *getCanonicalDecl(); + VarDecl *getCanonicalDecl(); const VarDecl *getCanonicalDecl() const { return const_cast(this)->getCanonicalDecl(); } @@ -1467,8 +1467,8 @@ public: 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 @@ public: SourceLocation getOuterLocStart() const; virtual SourceRange getSourceRange() const; - virtual TagDecl* getCanonicalDecl(); + TagDecl* getCanonicalDecl(); const TagDecl* getCanonicalDecl() const { return const_cast(this)->getCanonicalDecl(); } diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 1407dadd16cf..2ce43cb378b0 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -477,7 +477,7 @@ public: 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(this)->getCanonicalDecl(); } diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index d11ee8f7fd64..61f71e98659b 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -472,10 +472,10 @@ public: typedef std::reverse_iterator reverse_base_class_const_iterator; - virtual CXXRecordDecl *getCanonicalDecl() { + CXXRecordDecl *getCanonicalDecl() { return cast(RecordDecl::getCanonicalDecl()); } - virtual const CXXRecordDecl *getCanonicalDecl() const { + const CXXRecordDecl *getCanonicalDecl() const { return cast(RecordDecl::getCanonicalDecl()); } diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 81f5d39bf24c..df89b6f2a199 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -198,7 +198,7 @@ public: ImplementationControl impControl = None, unsigned numSelectorArgs = 0); - virtual ObjCMethodDecl *getCanonicalDecl(); + ObjCMethodDecl *getCanonicalDecl(); const ObjCMethodDecl *getCanonicalDecl() const { return const_cast(this)->getCanonicalDecl(); } diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index dfc5a6ae5d31..d8b7c9b5b00b 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -143,6 +143,29 @@ bool Decl::isDefinedOutsideFunctionOrMethod() const { return true; } +namespace { + template + inline Result *getSpecificCanonicalDecl(Decl *D, Result *(Class::*Get)()) { + return (llvm::cast(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