summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/ODRHash.cpp
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2017-02-23 03:25:57 +0000
committerRichard Trieu <rtrieu@google.com>2017-02-23 03:25:57 +0000
commitbcaaf96674ce687fe4736bf87a8d91b91da75fd6 (patch)
treef61560d66972171df8caae74b714cb5e542da837 /clang/lib/AST/ODRHash.cpp
parent185ced8b2ba848d58608a2df5fd048873e19814e (diff)
[ODRHash] Handle types in ODR hashing.
Fields will now have their types added to the hash, allowing for detection of mismatched field types. This detection allows the existing ODR checking to produce the correct message. Differential Revision: https://reviews.llvm.org/D21675 llvm-svn: 295931
Diffstat (limited to 'clang/lib/AST/ODRHash.cpp')
-rw-r--r--clang/lib/AST/ODRHash.cpp64
1 files changed, 62 insertions, 2 deletions
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 35af0e98a912..b75de54e07fb 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -102,6 +102,10 @@ public:
}
}
+ void AddQualType(QualType T) {
+ Hash.AddQualType(T);
+ }
+
void Visit(const Decl *D) {
ID.AddInteger(D->getKind());
Inherited::Visit(D);
@@ -112,6 +116,11 @@ public:
Inherited::VisitNamedDecl(D);
}
+ void VisitValueDecl(const ValueDecl *D) {
+ AddQualType(D->getType());
+ Inherited::VisitValueDecl(D);
+ }
+
void VisitAccessSpecDecl(const AccessSpecDecl *D) {
ID.AddInteger(D->getAccess());
Inherited::VisitAccessSpecDecl(D);
@@ -185,8 +194,59 @@ void ODRHash::AddDecl(const Decl *D) {
ID.AddInteger(D->getKind());
}
-void ODRHash::AddType(const Type *T) {}
-void ODRHash::AddQualType(QualType T) {}
+// Process a Type pointer. Add* methods call back into ODRHash while Visit*
+// methods process the relevant parts of the Type.
+class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
+ typedef TypeVisitor<ODRTypeVisitor> Inherited;
+ llvm::FoldingSetNodeID &ID;
+ ODRHash &Hash;
+
+public:
+ ODRTypeVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash)
+ : ID(ID), Hash(Hash) {}
+
+ void AddStmt(Stmt *S) {
+ Hash.AddBoolean(S);
+ if (S) {
+ Hash.AddStmt(S);
+ }
+ }
+
+ void Visit(const Type *T) {
+ ID.AddInteger(T->getTypeClass());
+ Inherited::Visit(T);
+ }
+
+ void VisitType(const Type *T) {}
+
+ void VisitBuiltinType(const BuiltinType *T) {
+ ID.AddInteger(T->getKind());
+ VisitType(T);
+ }
+};
+
+void ODRHash::AddType(const Type *T) {
+ assert(T && "Expecting non-null pointer.");
+ auto Result = TypeMap.insert(std::make_pair(T, TypeMap.size()));
+ ID.AddInteger(Result.first->second);
+ // On first encounter of a Type pointer, process it. Every time afterwards,
+ // only the index value is needed.
+ if (!Result.second) {
+ return;
+ }
+
+ ODRTypeVisitor(ID, *this).Visit(T);
+}
+
+void ODRHash::AddQualType(QualType T) {
+ AddBoolean(T.isNull());
+ if (T.isNull())
+ return;
+ SplitQualType split = T.split();
+ ID.AddInteger(split.Quals.getAsOpaqueValue());
+ AddType(split.Ty);
+}
+
void ODRHash::AddBoolean(bool Value) {
Bools.push_back(Value);
}