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);
|
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) {
|
void VisitQualifiers(Qualifiers Quals) {
|
||||||
ID.AddInteger(Quals.getAsOpaqueValue());
|
ID.AddInteger(Quals.getAsOpaqueValue());
|
||||||
}
|
}
|
||||||
|
@ -414,6 +428,42 @@ public:
|
||||||
AddQualType(T->getDecl()->getUnderlyingType().getCanonicalType());
|
AddQualType(T->getDecl()->getUnderlyingType().getCanonicalType());
|
||||||
VisitType(T);
|
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) {
|
void ODRHash::AddType(const Type *T) {
|
||||||
|
|
|
@ -634,6 +634,78 @@ S3 s3;
|
||||||
#endif
|
#endif
|
||||||
} // namespace Using
|
} // 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
|
// 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.
|
// while struct T should error at the access specifier mismatch at the end.
|
||||||
|
|
Loading…
Reference in New Issue