forked from OSchip/llvm-project
[ODRHash] Handle some template weirdness.
Build the index off of DeclarationName instead of Decl pointers. When finding an UnresolvedLookupExprClass, hash it as if it were a DeclRefExpr. This will allow methods to be hashed. llvm-svn: 325741
This commit is contained in:
parent
3c83937370
commit
f65efae5c4
|
@ -37,8 +37,9 @@ class TemplateParameterList;
|
|||
// Typically, only one Add* call is needed. clear can be called to reuse the
|
||||
// object.
|
||||
class ODRHash {
|
||||
// Use DenseMaps to convert between Decl and Type pointers and an index value.
|
||||
llvm::DenseMap<const Decl*, unsigned> DeclMap;
|
||||
// Use DenseMaps to convert from DeclarationName and Type pointers
|
||||
// to an index value.
|
||||
llvm::DenseMap<DeclarationName, unsigned> DeclNameMap;
|
||||
llvm::DenseMap<const Type*, unsigned> TypeMap;
|
||||
|
||||
// Save space by processing bools at the end.
|
||||
|
|
|
@ -33,6 +33,15 @@ void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) {
|
|||
}
|
||||
|
||||
void ODRHash::AddDeclarationName(DeclarationName Name) {
|
||||
// Index all DeclarationName and use index numbers to refer to them.
|
||||
auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size()));
|
||||
ID.AddInteger(Result.first->second);
|
||||
if (!Result.second) {
|
||||
// If found in map, the the DeclarationName has previously been processed.
|
||||
return;
|
||||
}
|
||||
|
||||
// First time processing each DeclarationName, also process its details.
|
||||
AddBoolean(Name.isEmpty());
|
||||
if (Name.isEmpty())
|
||||
return;
|
||||
|
@ -168,7 +177,7 @@ void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {
|
|||
}
|
||||
|
||||
void ODRHash::clear() {
|
||||
DeclMap.clear();
|
||||
DeclNameMap.clear();
|
||||
TypeMap.clear();
|
||||
Bools.clear();
|
||||
ID.clear();
|
||||
|
@ -418,7 +427,6 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) {
|
|||
|
||||
void ODRHash::AddSubDecl(const Decl *D) {
|
||||
assert(D && "Expecting non-null pointer.");
|
||||
AddDecl(D);
|
||||
|
||||
ODRDeclVisitor(ID, *this).Visit(D);
|
||||
}
|
||||
|
@ -476,9 +484,7 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function) {
|
|||
if (!Function->hasBody()) return;
|
||||
if (!Function->getBody()) return;
|
||||
|
||||
// TODO: Fix hashing for class methods.
|
||||
if (isa<CXXMethodDecl>(Function)) return;
|
||||
// And friend functions.
|
||||
// TODO: Fix hashing friend functions.
|
||||
if (Function->getFriendObjectKind()) return;
|
||||
|
||||
// Skip functions that are specializations or in specialization context.
|
||||
|
@ -504,19 +510,14 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function) {
|
|||
void ODRHash::AddDecl(const Decl *D) {
|
||||
assert(D && "Expecting non-null pointer.");
|
||||
D = D->getCanonicalDecl();
|
||||
auto Result = DeclMap.insert(std::make_pair(D, DeclMap.size()));
|
||||
ID.AddInteger(Result.first->second);
|
||||
// On first encounter of a Decl pointer, process it. Every time afterwards,
|
||||
// only the index value is needed.
|
||||
if (!Result.second) {
|
||||
|
||||
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
|
||||
AddDeclarationName(ND->getDeclName());
|
||||
return;
|
||||
}
|
||||
|
||||
ID.AddInteger(D->getKind());
|
||||
|
||||
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
|
||||
AddDeclarationName(ND->getDeclName());
|
||||
}
|
||||
// TODO: Handle non-NamedDecl here.
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -38,6 +38,8 @@ namespace {
|
|||
|
||||
void VisitStmt(const Stmt *S);
|
||||
|
||||
virtual void HandleStmtClass(Stmt::StmtClass SC) = 0;
|
||||
|
||||
#define STMT(Node, Base) void Visit##Node(const Node *S);
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
|
||||
|
@ -50,7 +52,7 @@ namespace {
|
|||
virtual void VisitType(QualType T) = 0;
|
||||
|
||||
/// \brief Visit a name that occurs within an expression or statement.
|
||||
virtual void VisitName(DeclarationName Name) = 0;
|
||||
virtual void VisitName(DeclarationName Name, bool TreatAsDecl = false) = 0;
|
||||
|
||||
/// \brief Visit identifiers that are not in Decl's or Type's.
|
||||
virtual void VisitIdentifierInfo(IdentifierInfo *II) = 0;
|
||||
|
@ -80,6 +82,10 @@ namespace {
|
|||
const ASTContext &Context, bool Canonical)
|
||||
: StmtProfiler(ID, Canonical), Context(Context) {}
|
||||
private:
|
||||
void HandleStmtClass(Stmt::StmtClass SC) override {
|
||||
ID.AddInteger(SC);
|
||||
}
|
||||
|
||||
void VisitDecl(const Decl *D) override {
|
||||
ID.AddInteger(D ? D->getKind() : 0);
|
||||
|
||||
|
@ -134,7 +140,7 @@ namespace {
|
|||
ID.AddPointer(T.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
void VisitName(DeclarationName Name) override {
|
||||
void VisitName(DeclarationName Name, bool /*TreatAsDecl*/) override {
|
||||
ID.AddPointer(Name.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
|
@ -163,11 +169,26 @@ namespace {
|
|||
: StmtProfiler(ID, false), Hash(Hash) {}
|
||||
|
||||
private:
|
||||
void HandleStmtClass(Stmt::StmtClass SC) override {
|
||||
if (SC == Stmt::UnresolvedLookupExprClass) {
|
||||
// Pretend that the name looked up is a Decl due to how templates
|
||||
// handle some Decl lookups.
|
||||
ID.AddInteger(Stmt::DeclRefExprClass);
|
||||
} else {
|
||||
ID.AddInteger(SC);
|
||||
}
|
||||
}
|
||||
|
||||
void VisitType(QualType T) override {
|
||||
Hash.AddQualType(T);
|
||||
}
|
||||
|
||||
void VisitName(DeclarationName Name) override {
|
||||
void VisitName(DeclarationName Name, bool TreatAsDecl) override {
|
||||
if (TreatAsDecl) {
|
||||
// A Decl can be null, so each Decl is preceded by a boolean to
|
||||
// store its nullness. Add a boolean here to match.
|
||||
ID.AddBoolean(true);
|
||||
}
|
||||
Hash.AddDeclarationName(Name);
|
||||
}
|
||||
void VisitIdentifierInfo(IdentifierInfo *II) override {
|
||||
|
@ -196,7 +217,9 @@ namespace {
|
|||
|
||||
void StmtProfiler::VisitStmt(const Stmt *S) {
|
||||
assert(S && "Requires non-null Stmt pointer");
|
||||
ID.AddInteger(S->getStmtClass());
|
||||
|
||||
HandleStmtClass(S->getStmtClass());
|
||||
|
||||
for (const Stmt *SubStmt : S->children()) {
|
||||
if (SubStmt)
|
||||
Visit(SubStmt);
|
||||
|
@ -1662,7 +1685,7 @@ StmtProfiler::VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *S) {
|
|||
void StmtProfiler::VisitOverloadExpr(const OverloadExpr *S) {
|
||||
VisitExpr(S);
|
||||
VisitNestedNameSpecifier(S->getQualifier());
|
||||
VisitName(S->getName());
|
||||
VisitName(S->getName(), /*TreatAsDecl*/ true);
|
||||
ID.AddBoolean(S->hasExplicitTemplateArgs());
|
||||
if (S->hasExplicitTemplateArgs())
|
||||
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
|
||||
|
|
Loading…
Reference in New Issue