forked from OSchip/llvm-project
[ODRHash] Support more types in the ODR checker.
Added support for TagType, TypeWithKeyword, and all children types. llvm-svn: 303231
This commit is contained in:
parent
4d5dd3b7ef
commit
58bb7bd18a
clang
|
@ -335,6 +335,20 @@ public:
|
|||
Hash.AddQualType(T);
|
||||
}
|
||||
|
||||
void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
|
||||
Hash.AddBoolean(NNS);
|
||||
if (NNS) {
|
||||
Hash.AddNestedNameSpecifier(NNS);
|
||||
}
|
||||
}
|
||||
|
||||
void AddIdentifierInfo(const IdentifierInfo *II) {
|
||||
Hash.AddBoolean(II);
|
||||
if (II) {
|
||||
Hash.AddIdentifierInfo(II);
|
||||
}
|
||||
}
|
||||
|
||||
void VisitQualifiers(Qualifiers Quals) {
|
||||
ID.AddInteger(Quals.getAsOpaqueValue());
|
||||
}
|
||||
|
@ -414,6 +428,42 @@ public:
|
|||
AddQualType(T->getDecl()->getUnderlyingType().getCanonicalType());
|
||||
VisitType(T);
|
||||
}
|
||||
|
||||
void VisitTagType(const TagType *T) {
|
||||
AddDecl(T->getDecl());
|
||||
VisitType(T);
|
||||
}
|
||||
|
||||
void VisitRecordType(const RecordType *T) { VisitTagType(T); }
|
||||
void VisitEnumType(const EnumType *T) { VisitTagType(T); }
|
||||
|
||||
void VisitTypeWithKeyword(const TypeWithKeyword *T) {
|
||||
ID.AddInteger(T->getKeyword());
|
||||
VisitType(T);
|
||||
};
|
||||
|
||||
void VisitDependentNameType(const DependentNameType *T) {
|
||||
AddNestedNameSpecifier(T->getQualifier());
|
||||
AddIdentifierInfo(T->getIdentifier());
|
||||
VisitTypeWithKeyword(T);
|
||||
}
|
||||
|
||||
void VisitDependentTemplateSpecializationType(
|
||||
const DependentTemplateSpecializationType *T) {
|
||||
AddIdentifierInfo(T->getIdentifier());
|
||||
AddNestedNameSpecifier(T->getQualifier());
|
||||
ID.AddInteger(T->getNumArgs());
|
||||
for (const auto &TA : T->template_arguments()) {
|
||||
Hash.AddTemplateArgument(TA);
|
||||
}
|
||||
VisitTypeWithKeyword(T);
|
||||
}
|
||||
|
||||
void VisitElaboratedType(const ElaboratedType *T) {
|
||||
AddNestedNameSpecifier(T->getQualifier());
|
||||
AddQualType(T->getNamedType());
|
||||
VisitTypeWithKeyword(T);
|
||||
}
|
||||
};
|
||||
|
||||
void ODRHash::AddType(const Type *T) {
|
||||
|
|
|
@ -634,6 +634,78 @@ S3 s3;
|
|||
#endif
|
||||
} // namespace Using
|
||||
|
||||
namespace RecordType {
|
||||
#if defined(FIRST)
|
||||
struct B1 {};
|
||||
struct S1 {
|
||||
B1 x;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
struct A1 {};
|
||||
struct S1 {
|
||||
A1 x;
|
||||
};
|
||||
#else
|
||||
S1 s1;
|
||||
// expected-error@first.h:* {{'RecordType::S1::x' from module 'FirstModule' is not present in definition of 'RecordType::S1' in module 'SecondModule'}}
|
||||
// expected-note@second.h:* {{declaration of 'x' does not match}}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace DependentType {
|
||||
#if defined(FIRST)
|
||||
template <class T>
|
||||
class S1 {
|
||||
typename T::typeA x;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
template <class T>
|
||||
class S1 {
|
||||
typename T::typeB x;
|
||||
};
|
||||
#else
|
||||
template<class T>
|
||||
using U1 = S1<T>;
|
||||
// expected-error@first.h:* {{'DependentType::S1::x' from module 'FirstModule' is not present in definition of 'S1<T>' in module 'SecondModule'}}
|
||||
// expected-note@second.h:* {{declaration of 'x' does not match}}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace ElaboratedType {
|
||||
#if defined(FIRST)
|
||||
namespace N1 { using type = double; }
|
||||
struct S1 {
|
||||
N1::type x;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
namespace N1 { using type = int; }
|
||||
struct S1 {
|
||||
N1::type x;
|
||||
};
|
||||
#else
|
||||
S1 s1;
|
||||
// expected-error@first.h:* {{'ElaboratedType::S1::x' from module 'FirstModule' is not present in definition of 'ElaboratedType::S1' in module 'SecondModule'}}
|
||||
// expected-note@second.h:* {{declaration of 'x' does not match}}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace Enum {
|
||||
#if defined(FIRST)
|
||||
enum A1 {};
|
||||
struct S1 {
|
||||
A1 x;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
enum A2 {};
|
||||
struct S1 {
|
||||
A2 x;
|
||||
};
|
||||
#else
|
||||
S1 s1;
|
||||
// expected-error@first.h:* {{'Enum::S1::x' from module 'FirstModule' is not present in definition of 'Enum::S1' in module 'SecondModule'}}
|
||||
// expected-note@second.h:* {{declaration of 'x' does not match}}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Interesting cases that should not cause errors. struct S should not error
|
||||
// while struct T should error at the access specifier mismatch at the end.
|
||||
|
|
Loading…
Reference in New Issue