diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/AST/ODRHash.cpp | |
parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) |
Notes
Diffstat (limited to 'lib/AST/ODRHash.cpp')
-rw-r--r-- | lib/AST/ODRHash.cpp | 212 |
1 files changed, 158 insertions, 54 deletions
diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index 088d8bedd453..e710d3780337 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -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; @@ -139,6 +148,8 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) { AddQualType(TA.getAsType()); break; case TemplateArgument::Declaration: + AddDecl(TA.getAsDecl()); + break; case TemplateArgument::NullPtr: case TemplateArgument::Integral: break; @@ -168,8 +179,7 @@ void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) { } void ODRHash::clear() { - DeclMap.clear(); - TypeMap.clear(); + DeclNameMap.clear(); Bools.clear(); ID.clear(); } @@ -307,26 +317,14 @@ public: } void VisitFunctionDecl(const FunctionDecl *D) { - ID.AddInteger(D->getStorageClass()); - Hash.AddBoolean(D->isInlineSpecified()); - Hash.AddBoolean(D->isVirtualAsWritten()); - Hash.AddBoolean(D->isPure()); - Hash.AddBoolean(D->isDeletedAsWritten()); - - ID.AddInteger(D->param_size()); - - for (auto *Param : D->parameters()) { - Hash.AddSubDecl(Param); - } - - AddQualType(D->getReturnType()); + // Handled by the ODRHash for FunctionDecl + ID.AddInteger(D->getODRHash()); Inherited::VisitFunctionDecl(D); } void VisitCXXMethodDecl(const CXXMethodDecl *D) { - Hash.AddBoolean(D->isConst()); - Hash.AddBoolean(D->isVolatile()); + // Handled by the ODRHash for FunctionDecl Inherited::VisitCXXMethodDecl(D); } @@ -363,6 +361,7 @@ public: if (hasDefaultArgument) { AddTemplateArgument(D->getDefaultArgument()); } + Hash.AddBoolean(D->isParameterPack()); Inherited::VisitTemplateTypeParmDecl(D); } @@ -375,6 +374,7 @@ public: if (hasDefaultArgument) { AddStmt(D->getDefaultArgument()); } + Hash.AddBoolean(D->isParameterPack()); Inherited::VisitNonTypeTemplateParmDecl(D); } @@ -387,15 +387,37 @@ public: if (hasDefaultArgument) { AddTemplateArgument(D->getDefaultArgument().getArgument()); } + Hash.AddBoolean(D->isParameterPack()); Inherited::VisitTemplateTemplateParmDecl(D); } + + void VisitTemplateDecl(const TemplateDecl *D) { + Hash.AddTemplateParameterList(D->getTemplateParameters()); + + Inherited::VisitTemplateDecl(D); + } + + void VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl *D) { + Hash.AddBoolean(D->isMemberSpecialization()); + Inherited::VisitRedeclarableTemplateDecl(D); + } + + void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { + AddDecl(D->getTemplatedDecl()); + Inherited::VisitFunctionTemplateDecl(D); + } + + void VisitEnumConstantDecl(const EnumConstantDecl *D) { + AddStmt(D->getInitExpr()); + Inherited::VisitEnumConstantDecl(D); + } }; } // namespace // Only allow a small portion of Decl's to be processed. Remove this once // all Decl's can be handled. -bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) { +bool ODRHash::isWhitelistedDecl(const Decl *D, const DeclContext *Parent) { if (D->isImplicit()) return false; if (D->getDeclContext() != Parent) return false; @@ -406,8 +428,10 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) { case Decl::CXXConstructor: case Decl::CXXDestructor: case Decl::CXXMethod: + case Decl::EnumConstant: // Only found in EnumDecl's. case Decl::Field: case Decl::Friend: + case Decl::FunctionTemplate: case Decl::StaticAssert: case Decl::TypeAlias: case Decl::Typedef: @@ -418,7 +442,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); } @@ -440,9 +463,13 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { // Filter out sub-Decls which will not be processed in order to get an // accurate count of Decl's. llvm::SmallVector<const Decl *, 16> Decls; - for (const Decl *SubDecl : Record->decls()) { + for (Decl *SubDecl : Record->decls()) { if (isWhitelistedDecl(SubDecl, Record)) { Decls.push_back(SubDecl); + if (auto *Function = dyn_cast<FunctionDecl>(SubDecl)) { + // Compute/Preload ODRHash into FunctionDecl. + Function->getODRHash(); + } } } @@ -466,28 +493,48 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { } } -void ODRHash::AddFunctionDecl(const FunctionDecl *Function) { +void ODRHash::AddFunctionDecl(const FunctionDecl *Function, + bool SkipBody) { assert(Function && "Expecting non-null pointer."); - // Skip hashing these kinds of function. - if (Function->isImplicit()) return; - if (Function->isDefaulted()) return; - if (Function->isDeleted()) return; - if (!Function->hasBody()) return; - if (!Function->getBody()) return; - - // TODO: Fix hashing for class methods. - if (isa<CXXMethodDecl>(Function)) return; - // Skip functions that are specializations or in specialization context. const DeclContext *DC = Function; while (DC) { if (isa<ClassTemplateSpecializationDecl>(DC)) return; - if (auto *F = dyn_cast<FunctionDecl>(DC)) - if (F->isFunctionTemplateSpecialization()) return; + if (auto *F = dyn_cast<FunctionDecl>(DC)) { + if (F->isFunctionTemplateSpecialization()) { + if (!isa<CXXMethodDecl>(DC)) return; + if (DC->getLexicalParent()->isFileContext()) return; + // Inline method specializations are the only supported + // specialization for now. + } + } DC = DC->getParent(); } + ID.AddInteger(Function->getDeclKind()); + + const auto *SpecializationArgs = Function->getTemplateSpecializationArgs(); + AddBoolean(SpecializationArgs); + if (SpecializationArgs) { + ID.AddInteger(SpecializationArgs->size()); + for (const TemplateArgument &TA : SpecializationArgs->asArray()) { + AddTemplateArgument(TA); + } + } + + if (const auto *Method = dyn_cast<CXXMethodDecl>(Function)) { + AddBoolean(Method->isConst()); + AddBoolean(Method->isVolatile()); + } + + ID.AddInteger(Function->getStorageClass()); + AddBoolean(Function->isInlineSpecified()); + AddBoolean(Function->isVirtualAsWritten()); + AddBoolean(Function->isPure()); + AddBoolean(Function->isDeletedAsWritten()); + AddBoolean(Function->isExplicitlyDefaulted()); + AddDecl(Function); AddQualType(Function->getReturnType()); @@ -496,25 +543,62 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function) { for (auto Param : Function->parameters()) AddSubDecl(Param); - AddStmt(Function->getBody()); + if (SkipBody) { + AddBoolean(false); + return; + } + + const bool HasBody = Function->isThisDeclarationADefinition() && + !Function->isDefaulted() && !Function->isDeleted() && + !Function->isLateTemplateParsed(); + AddBoolean(HasBody); + if (HasBody) { + auto *Body = Function->getBody(); + AddBoolean(Body); + if (Body) + AddStmt(Body); + } +} + +void ODRHash::AddEnumDecl(const EnumDecl *Enum) { + assert(Enum); + AddDeclarationName(Enum->getDeclName()); + + AddBoolean(Enum->isScoped()); + if (Enum->isScoped()) + AddBoolean(Enum->isScopedUsingClassTag()); + + if (Enum->getIntegerTypeSourceInfo()) + AddQualType(Enum->getIntegerType()); + + // Filter out sub-Decls which will not be processed in order to get an + // accurate count of Decl's. + llvm::SmallVector<const Decl *, 16> Decls; + for (Decl *SubDecl : Enum->decls()) { + if (isWhitelistedDecl(SubDecl, Enum)) { + assert(isa<EnumConstantDecl>(SubDecl) && "Unexpected Decl"); + Decls.push_back(SubDecl); + } + } + + ID.AddInteger(Decls.size()); + for (auto SubDecl : Decls) { + AddSubDecl(SubDecl); + } + } 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 { @@ -642,13 +726,41 @@ public: VisitFunctionType(T); } + void VisitPointerType(const PointerType *T) { + AddQualType(T->getPointeeType()); + VisitType(T); + } + + void VisitReferenceType(const ReferenceType *T) { + AddQualType(T->getPointeeTypeAsWritten()); + VisitType(T); + } + + void VisitLValueReferenceType(const LValueReferenceType *T) { + VisitReferenceType(T); + } + + void VisitRValueReferenceType(const RValueReferenceType *T) { + VisitReferenceType(T); + } + void VisitTypedefType(const TypedefType *T) { AddDecl(T->getDecl()); QualType UnderlyingType = T->getDecl()->getUnderlyingType(); VisitQualifiers(UnderlyingType.getQualifiers()); - while (const TypedefType *Underlying = - dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) { - UnderlyingType = Underlying->getDecl()->getUnderlyingType(); + while (true) { + if (const TypedefType *Underlying = + dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) { + UnderlyingType = Underlying->getDecl()->getUnderlyingType(); + continue; + } + if (const ElaboratedType *Underlying = + dyn_cast<ElaboratedType>(UnderlyingType.getTypePtr())) { + UnderlyingType = Underlying->getNamedType(); + continue; + } + + break; } AddType(UnderlyingType.getTypePtr()); VisitType(T); @@ -710,14 +822,6 @@ public: 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); } |