summaryrefslogtreecommitdiff
path: root/lib/AST/ODRHash.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
commit2298981669bf3bd63335a4be179bc0f96823a8f4 (patch)
tree1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/AST/ODRHash.cpp
parent9a83721404652cea39e9f02ae3e3b5c964602a5c (diff)
Notes
Diffstat (limited to 'lib/AST/ODRHash.cpp')
-rw-r--r--lib/AST/ODRHash.cpp90
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);
}