From d05a006a537bc5860eec042c2c541ccdbb182a02 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Fri, 19 May 2017 20:05:16 +0000 Subject: [PATCH] [ODRHash] Support TemplateName and TemplateArgument llvm-svn: 303450 --- clang/lib/AST/ODRHash.cpp | 92 +++++++++++++++++++++++++++++++++++- clang/test/Modules/odr_hash.cpp | 102 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 24371db..080b6ac 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -110,8 +110,88 @@ void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { } } -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) { diff --git a/clang/test/Modules/odr_hash.cpp b/clang/test/Modules/odr_hash.cpp index 947583b..111bd38 100644 --- a/clang/test/Modules/odr_hash.cpp +++ b/clang/test/Modules/odr_hash.cpp @@ -866,6 +866,108 @@ S9 s9; #endif } +namespace TemplateArgument { +#if defined(FIRST) +template struct A1 {}; +struct S1 { + A1 x; +}; +#elif defined(SECOND) +template struct A1 {}; +struct S1 { + A1 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 struct A2 {}; +struct S2 { + A2 x; +}; +#elif defined(SECOND) +template struct A2 {}; +struct S2 { + A2 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 struct A3 {}; +struct S3 { + A3 x; +}; +#elif defined(SECOND) +template struct B3 {}; +struct S3 { + B3 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 struct A4 {}; +struct S4 { + A4 x; +}; +#elif defined(SECOND) +template struct A4 {}; +struct S4 { + A4 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'}} +// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'A4'}} +#endif + +#if defined(FIRST) +int x5; +template struct A5 {}; +struct S5 { + A5 x; +}; +#elif defined(SECOND) +int x5; +template 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 struct A6 {}; +struct S6 { + A6<&x6> x; +}; +#elif defined(SECOND) +int y6; +template 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 { -- 2.7.4