summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/ODRHash.cpp
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2019-06-22 00:32:19 +0000
committerRichard Trieu <rtrieu@google.com>2019-06-22 00:32:19 +0000
commit82df97ca8e699bb984046e2dce2d9023189cfcb8 (patch)
treef744adecc7e4102f6b14121a93a9961cdf570677 /clang/lib/AST/ODRHash.cpp
parent0eb966c8248b290385980ffdad26553a520ace13 (diff)
downloadbcm5719-llvm-82df97ca8e699bb984046e2dce2d9023189cfcb8.tar.gz
bcm5719-llvm-82df97ca8e699bb984046e2dce2d9023189cfcb8.zip
[ODRHash] Skip some typedef types.
In some cases, a typedef only strips aways a keyword for a type, keeping the same name as the root record type. This causes some confusion when the type is defined in one modules but only forward declared in another. Skipping the typedef and going straight to the record will avoid this issue. typedef struct S {} S; S* s; // S is TypedefType here struct S; S* s; // S is RecordType here llvm-svn: 364119
Diffstat (limited to 'clang/lib/AST/ODRHash.cpp')
-rw-r--r--clang/lib/AST/ODRHash.cpp45
1 files changed, 45 insertions, 0 deletions
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index ba3b2ee49c5..e47154088d9 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -696,7 +696,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);
}
OpenPOWER on IntegriCloud