Author: rtrieu Date: Fri May 19 15:05:16 2017 New Revision: 303450 URL: http://llvm.org/viewvc/llvm-project?rev=303450&view=rev Log: [ODRHash] Support TemplateName and TemplateArgument
Modified: cfe/trunk/lib/AST/ODRHash.cpp cfe/trunk/test/Modules/odr_hash.cpp Modified: cfe/trunk/lib/AST/ODRHash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=303450&r1=303449&r2=303450&view=diff ============================================================================== --- cfe/trunk/lib/AST/ODRHash.cpp (original) +++ cfe/trunk/lib/AST/ODRHash.cpp Fri May 19 15:05:16 2017 @@ -110,8 +110,88 @@ void ODRHash::AddNestedNameSpecifier(con } } -void ODRHash::AddTemplateName(TemplateName Name) {} -void ODRHash::AddTemplateArgument(TemplateArgument TA) {} +void ODRHash::AddTemplateName(TemplateName Name) { + const auto Kind = Name.getKind(); + ID.AddInteger(Kind); + AddBoolean(Name.isDependent()); + AddBoolean(Name.isInstantiationDependent()); + switch (Kind) { + case TemplateName::Template: + AddDecl(Name.getAsTemplateDecl()); + break; + case TemplateName::OverloadedTemplate: { + const auto *Storage = Name.getAsOverloadedTemplate(); + ID.AddInteger(Storage->size()); + for (const auto *ND : *Storage) { + AddDecl(ND); + } + break; + } + case TemplateName::QualifiedTemplate: { + const auto *QTN = Name.getAsQualifiedTemplateName(); + AddNestedNameSpecifier(QTN->getQualifier()); + AddBoolean(QTN->hasTemplateKeyword()); + AddDecl(QTN->getDecl()); + break; + } + case TemplateName::DependentTemplate: { + const auto *DTN = Name.getAsDependentTemplateName(); + AddBoolean(DTN->isIdentifier()); + if (DTN->isIdentifier()) { + AddIdentifierInfo(DTN->getIdentifier()); + } else { + ID.AddInteger(DTN->getOperator()); + } + break; + } + case TemplateName::SubstTemplateTemplateParm: { + const auto *Storage = Name.getAsSubstTemplateTemplateParm(); + AddDecl(Storage->getParameter()); + AddTemplateName(Storage->getReplacement()); + break; + } + case TemplateName::SubstTemplateTemplateParmPack: { + const auto *Storage = Name.getAsSubstTemplateTemplateParmPack(); + AddDecl(Storage->getParameterPack()); + AddTemplateArgument(Storage->getArgumentPack()); + break; + } + } +} + +void ODRHash::AddTemplateArgument(TemplateArgument TA) { + const auto Kind = TA.getKind(); + ID.AddInteger(Kind); + switch (Kind) { + case TemplateArgument::Null: + llvm_unreachable("Require valid TemplateArgument"); + case TemplateArgument::Type: + AddQualType(TA.getAsType()); + break; + case TemplateArgument::Declaration: + AddDecl(TA.getAsDecl()); + break; + case TemplateArgument::NullPtr: + AddQualType(TA.getNullPtrType()); + break; + case TemplateArgument::Integral: + TA.getAsIntegral().Profile(ID); + AddQualType(TA.getIntegralType()); + break; + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + AddTemplateName(TA.getAsTemplateOrTemplatePattern()); + break; + case TemplateArgument::Expression: + AddStmt(TA.getAsExpr()); + break; + case TemplateArgument::Pack: + ID.AddInteger(TA.pack_size()); + for (auto SubTA : TA.pack_elements()) + AddTemplateArgument(SubTA); + break; + } +} void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {} void ODRHash::clear() { @@ -492,6 +572,14 @@ public: AddQualType(T->getNamedType()); VisitTypeWithKeyword(T); } + + void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { + ID.AddInteger(T->getNumArgs()); + for (const auto &TA : T->template_arguments()) { + Hash.AddTemplateArgument(TA); + } + Hash.AddTemplateName(T->getTemplateName()); + } }; void ODRHash::AddType(const Type *T) { Modified: cfe/trunk/test/Modules/odr_hash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=303450&r1=303449&r2=303450&view=diff ============================================================================== --- cfe/trunk/test/Modules/odr_hash.cpp (original) +++ cfe/trunk/test/Modules/odr_hash.cpp Fri May 19 15:05:16 2017 @@ -866,6 +866,108 @@ S9 s9; #endif } +namespace TemplateArgument { +#if defined(FIRST) +template <typename ...T> struct A1 {}; +struct S1 { + A1<int> x; +}; +#elif defined(SECOND) +template <typename ...T> struct A1 {}; +struct S1 { + A1<int, int> x; +}; +#else +S1 s1; +// expected-error@first.h:* {{'TemplateArgument::S1::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S1' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'x' does not match}} +#endif + +#if defined(FIRST) +template <typename T> struct A2 {}; +struct S2 { + A2<int> x; +}; +#elif defined(SECOND) +template <typename T> struct A2 {}; +struct S2 { + A2<short> x; +}; +#else +S2 s2; +// expected-error@first.h:* {{'TemplateArgument::S2::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S2' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'x' does not match}} +#endif + +#if defined(FIRST) +template <typename T> struct A3 {}; +struct S3 { + A3<int> x; +}; +#elif defined(SECOND) +template <typename T> struct B3 {}; +struct S3 { + B3<int> x; +}; +#else +S3 s3; +// expected-error@first.h:* {{'TemplateArgument::S3::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S3' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'x' does not match}} +#endif + +#if defined(FIRST) +template <typename T, T t> struct A4 {}; +struct S4 { + A4<int, 5> x; +}; +#elif defined(SECOND) +template <typename T, T t> struct A4 {}; +struct S4 { + A4<int, 5 + 0> x; +}; +#else +S4 s4; +// expected-error@second.h:* {{'TemplateArgument::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'A4<int, 5 + 0>'}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'A4<int, 5>'}} +#endif + +#if defined(FIRST) +int x5; +template <int *ptr> struct A5 {}; +struct S5 { + A5<nullptr> x; +}; +#elif defined(SECOND) +int x5; +template <int *ptr> struct A5 {}; +struct S5 { + A5<&x5> x; +}; +#else +S5 s5; +// expected-error@first.h:* {{'TemplateArgument::S5::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S5' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'x' does not match}} +#endif + +#if defined(FIRST) +int x6; +template <int *ptr> struct A6 {}; +struct S6 { + A6<&x6> x; +}; +#elif defined(SECOND) +int y6; +template <int *ptr> struct A6 {}; +struct S6 { + A6<&y6> x; +}; +#else +S6 s6; +// expected-error@first.h:* {{'TemplateArgument::S6::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S6' 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. namespace AllDecls { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits