diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 |
commit | 2298981669bf3bd63335a4be179bc0f96823a8f4 (patch) | |
tree | 1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/AST/ODRHash.cpp | |
parent | 9a83721404652cea39e9f02ae3e3b5c964602a5c (diff) |
Notes
Diffstat (limited to 'lib/AST/ODRHash.cpp')
-rw-r--r-- | lib/AST/ODRHash.cpp | 90 |
1 files changed, 81 insertions, 9 deletions
diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index a4c344ce0a9b..3b89c630b451 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -1,9 +1,8 @@ //===-- ODRHash.cpp - Hashing to diagnose ODR failures ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -72,8 +71,13 @@ void ODRHash::AddDeclarationNameImpl(DeclarationName Name) { AddBoolean(S.isKeywordSelector()); AddBoolean(S.isUnarySelector()); unsigned NumArgs = S.getNumArgs(); + ID.AddInteger(NumArgs); for (unsigned i = 0; i < NumArgs; ++i) { - AddIdentifierInfo(S.getIdentifierInfoForSlot(i)); + const IdentifierInfo *II = S.getIdentifierInfoForSlot(i); + AddBoolean(II); + if (II) { + AddIdentifierInfo(II); + } } break; } @@ -141,6 +145,7 @@ void ODRHash::AddTemplateName(TemplateName Name) { break; // TODO: Support these cases. case TemplateName::OverloadedTemplate: + case TemplateName::AssumedTemplate: case TemplateName::QualifiedTemplate: case TemplateName::DependentTemplate: case TemplateName::SubstTemplateTemplateParm: @@ -696,7 +701,52 @@ public: ID.AddInteger(Quals.getAsOpaqueValue()); } + // Return the RecordType if the typedef only strips away a keyword. + // Otherwise, return the original type. + static const Type *RemoveTypedef(const Type *T) { + const auto *TypedefT = dyn_cast<TypedefType>(T); + if (!TypedefT) { + return T; + } + + const TypedefNameDecl *D = TypedefT->getDecl(); + QualType UnderlyingType = D->getUnderlyingType(); + + if (UnderlyingType.hasLocalQualifiers()) { + return T; + } + + const auto *ElaboratedT = dyn_cast<ElaboratedType>(UnderlyingType); + if (!ElaboratedT) { + return T; + } + + if (ElaboratedT->getQualifier() != nullptr) { + return T; + } + + QualType NamedType = ElaboratedT->getNamedType(); + if (NamedType.hasLocalQualifiers()) { + return T; + } + + const auto *RecordT = dyn_cast<RecordType>(NamedType); + if (!RecordT) { + return T; + } + + const IdentifierInfo *TypedefII = TypedefT->getDecl()->getIdentifier(); + const IdentifierInfo *RecordII = RecordT->getDecl()->getIdentifier(); + if (!TypedefII || !RecordII || + TypedefII->getName() != RecordII->getName()) { + return T; + } + + return RecordT; + } + void Visit(const Type *T) { + T = RemoveTypedef(T); ID.AddInteger(T->getTypeClass()); Inherited::Visit(T); } @@ -704,14 +754,36 @@ public: void VisitType(const Type *T) {} void VisitAdjustedType(const AdjustedType *T) { - AddQualType(T->getOriginalType()); - AddQualType(T->getAdjustedType()); + QualType Original = T->getOriginalType(); + QualType Adjusted = T->getAdjustedType(); + + // The original type and pointee type can be the same, as in the case of + // function pointers decaying to themselves. Set a bool and only process + // the type once, to prevent doubling the work. + SplitQualType split = Adjusted.split(); + if (auto Pointer = dyn_cast<PointerType>(split.Ty)) { + if (Pointer->getPointeeType() == Original) { + Hash.AddBoolean(true); + ID.AddInteger(split.Quals.getAsOpaqueValue()); + AddQualType(Original); + VisitType(T); + return; + } + } + + // The original type and pointee type are different, such as in the case + // of a array decaying to an element pointer. Set a bool to false and + // process both types. + Hash.AddBoolean(false); + AddQualType(Original); + AddQualType(Adjusted); + VisitType(T); } void VisitDecayedType(const DecayedType *T) { - AddQualType(T->getDecayedType()); - AddQualType(T->getPointeeType()); + // getDecayedType and getPointeeType are derived from getAdjustedType + // and don't need to be separately processed. VisitAdjustedType(T); } |