diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/AST/ODRHash.cpp | 64 | ||||
-rw-r--r-- | clang/test/Modules/odr_hash.cpp | 14 |
2 files changed, 76 insertions, 2 deletions
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 35af0e98a91..b75de54e07f 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); } diff --git a/clang/test/Modules/odr_hash.cpp b/clang/test/Modules/odr_hash.cpp index 2b2a788efc7..7b696346be3 100644 --- a/clang/test/Modules/odr_hash.cpp +++ b/clang/test/Modules/odr_hash.cpp @@ -148,6 +148,20 @@ S2 s2; // expected-error@second.h:* {{'Field::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'y'}} // expected-note@first.h:* {{but in 'FirstModule' found field 'x'}} #endif + +#if defined(FIRST) +struct S3 { + double x; +}; +#elif defined(SECOND) +struct S3 { + int x; +}; +#else +S3 s3; +// expected-error@first.h:* {{'Field::S3::x' from module 'FirstModule' is not present in definition of 'Field::S3' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'x' does not match}} +#endif } // namespace Field // Naive parsing of AST can lead to cycles in processing. Ensure |