}
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;
}
void ODRHash::clear() {
- DeclMap.clear();
+ DeclNameMap.clear();
TypeMap.clear();
Bools.clear();
ID.clear();
void ODRHash::AddSubDecl(const Decl *D) {
assert(D && "Expecting non-null pointer.");
- AddDecl(D);
ODRDeclVisitor(ID, *this).Visit(D);
}
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.
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) {
- return;
- }
-
- ID.AddInteger(D->getKind());
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
AddDeclarationName(ND->getDeclName());
+ return;
}
+
+ ID.AddInteger(D->getKind());
+ // TODO: Handle non-NamedDecl here.
}
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"
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;
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);
ID.AddPointer(T.getAsOpaquePtr());
}
- void VisitName(DeclarationName Name) override {
+ void VisitName(DeclarationName Name, bool /*TreatAsDecl*/) override {
ID.AddPointer(Name.getAsOpaquePtr());
}
: 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 {
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);
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());