1//===-- ODRHash.h - Hashing to diagnose ODR failures ------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file contains the declaration of the ODRHash class, which calculates
11/// a hash based on AST nodes, which is stable across different runs.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_AST_ODRHASH_H
16#define LLVM_CLANG_AST_ODRHASH_H
17
18#include "clang/AST/DeclarationName.h"
19#include "clang/AST/Type.h"
20#include "clang/AST/TemplateBase.h"
21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/FoldingSet.h"
23#include "llvm/ADT/PointerUnion.h"
24#include "llvm/ADT/SmallVector.h"
25
26namespace clang {
27
28class APValue;
29class Decl;
30class IdentifierInfo;
31class NestedNameSpecifier;
32class Stmt;
33class TemplateParameterList;
34
35// ODRHash is used to calculate a hash based on AST node contents that
36// does not rely on pointer addresses. This allows the hash to not vary
37// between runs and is usable to detect ODR problems in modules. To use,
38// construct an ODRHash object, then call Add* methods over the nodes that
39// need to be hashed. Then call CalculateHash to get the hash value.
40// Typically, only one Add* call is needed. clear can be called to reuse the
41// object.
42class ODRHash {
43 // Use DenseMaps to convert from DeclarationName and Type pointers
44 // to an index value.
45 llvm::DenseMap<DeclarationName, unsigned> DeclNameMap;
46
47 // Save space by processing bools at the end.
48 llvm::SmallVector<bool, 128> Bools;
49
50 llvm::FoldingSetNodeID ID;
51
52public:
53 ODRHash() {}
54
55 // Use this for ODR checking classes between modules. This method compares
56 // more information than the AddDecl class.
57 void AddCXXRecordDecl(const CXXRecordDecl *Record);
58
59 // Use this for ODR checking records in C/Objective-C between modules. This
60 // method compares more information than the AddDecl class.
61 void AddRecordDecl(const RecordDecl *Record);
62
63 // Use this for ODR checking ObjC interfaces. This
64 // method compares more information than the AddDecl class.
65 void AddObjCInterfaceDecl(const ObjCInterfaceDecl *Record);
66
67 // Use this for ODR checking functions between modules. This method compares
68 // more information than the AddDecl class. SkipBody will process the
69 // hash as if the function has no body.
70 void AddFunctionDecl(const FunctionDecl *Function, bool SkipBody = false);
71
72 // Use this for ODR checking enums between modules. This method compares
73 // more information than the AddDecl class.
74 void AddEnumDecl(const EnumDecl *Enum);
75
76 // Use this for ODR checking ObjC protocols. This
77 // method compares more information than the AddDecl class.
78 void AddObjCProtocolDecl(const ObjCProtocolDecl *P);
79
80 // Process SubDecls of the main Decl. This method calls the DeclVisitor
81 // while AddDecl does not.
82 void AddSubDecl(const Decl *D);
83
84 // Reset the object for reuse.
85 void clear();
86
87 // Add booleans to ID and uses it to calculate the hash.
88 unsigned CalculateHash();
89
90 // Add AST nodes that need to be processed.
91 void AddDecl(const Decl *D);
92 void AddType(const Type *T);
93 void AddQualType(QualType T);
94 void AddStmt(const Stmt *S);
95 void AddIdentifierInfo(const IdentifierInfo *II);
96 void AddNestedNameSpecifier(const NestedNameSpecifier *NNS);
97 void AddTemplateName(TemplateName Name);
98 void AddDeclarationName(DeclarationName Name, bool TreatAsDecl = false);
99 void AddTemplateArgument(TemplateArgument TA);
100 void AddTemplateParameterList(const TemplateParameterList *TPL);
101
102 // Save booleans until the end to lower the size of data to process.
103 void AddBoolean(bool value);
104
105 void AddStructuralValue(const APValue &);
106
107 static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent);
108
109private:
110 void AddDeclarationNameImpl(DeclarationName Name);
111};
112
113} // end namespace clang
114
115#endif
116