diff options
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 a4c344ce0a9b1..3b89c630b451e 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);    }  | 
