[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
This commit is contained in:
parent
0eb966c824
commit
82df97ca8e
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -4621,9 +4621,70 @@ struct S2 {
|
|||
#else
|
||||
S2 s2;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
namespace TypedefStruct {
|
||||
#if defined(FIRST)
|
||||
struct T1;
|
||||
class S1 {
|
||||
T1* t;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
typedef struct T1 {} T1;
|
||||
class S1 {
|
||||
T1* t;
|
||||
};
|
||||
#else
|
||||
S1 s1;
|
||||
#endif
|
||||
|
||||
#if defined(FIRST)
|
||||
struct T2;
|
||||
class S2 {
|
||||
const T2* t = nullptr;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
typedef struct T2 {} T2;
|
||||
class S2 {
|
||||
const T2* t = nullptr;
|
||||
};
|
||||
#else
|
||||
S2 s2;
|
||||
#endif
|
||||
|
||||
#if defined(FIRST)
|
||||
struct T3;
|
||||
class S3 {
|
||||
T3* const t = nullptr;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
typedef struct T3 {} T3;
|
||||
class S3 {
|
||||
T3* const t = nullptr;
|
||||
};
|
||||
#else
|
||||
S3 s3;
|
||||
#endif
|
||||
|
||||
#if defined(FIRST)
|
||||
namespace NS4 {
|
||||
struct T4;
|
||||
} // namespace NS4
|
||||
class S4 {
|
||||
NS4::T4* t = 0;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
namespace NS4 {
|
||||
typedef struct T4 {} T4;
|
||||
} // namespace NS4
|
||||
class S4 {
|
||||
NS4::T4* t = 0;
|
||||
};
|
||||
#else
|
||||
S4 s4;
|
||||
#endif
|
||||
} // namespace TypedefStruct
|
||||
|
||||
// Keep macros contained to one file.
|
||||
#ifdef FIRST
|
||||
#undef FIRST
|
||||
|
|
Loading…
Reference in New Issue