Author: rtrieu Date: Tue May 29 18:12:26 2018 New Revision: 333486 URL: http://llvm.org/viewvc/llvm-project?rev=333486&view=rev Log: [ODRHash] Support FunctionTemplateDecl in records.
Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td cfe/trunk/lib/AST/ODRHash.cpp cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/test/Modules/odr_hash.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td?rev=333486&r1=333485&r2=333486&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Tue May 29 18:12:26 2018 @@ -168,11 +168,11 @@ def err_module_odr_violation_mismatch_de "%select{definition in module '%2'|defined here}1 found " "%select{end of class|public access specifier|private access specifier|" "protected access specifier|static assert|field|method|type alias|typedef|" - "data member|friend declaration}3">; + "data member|friend declaration|function template}3">; def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found " "%select{end of class|public access specifier|private access specifier|" "protected access specifier|static assert|field|method|type alias|typedef|" - "data member|friend declaration}1">; + "data member|friend declaration|function template}1">; def err_module_odr_violation_mismatch_decl_diff : Error< "%q0 has different definitions in different modules; first difference is " @@ -227,6 +227,18 @@ def err_module_odr_violation_mismatch_de "friend %select{class|function}4|" "friend %4|" "friend function %4|" + "function template %4 with %5 template parameter%s5|" + "function template %4 with %ordinal5 template parameter being a " + "%select{type|non-type|template}6 template parameter|" + "function template %4 with %ordinal5 template parameter " + "%select{with no name|named %7}6|" + "function template %4 with %ordinal5 template parameter with " + "%select{no |}6default argument|" + "function template %4 with %ordinal5 template parameter with " + "default argument %6|" + "function template %4 with %ordinal5 template parameter with one type|" + "function template %4 with %ordinal5 template parameter %select{not |}6" + "being a template parameter pack|" "}3">; def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " @@ -280,6 +292,18 @@ def note_module_odr_violation_mismatch_d "friend %select{class|function}2|" "friend %2|" "friend function %2|" + "function template %2 with %3 template parameter%s3|" + "function template %2 with %ordinal3 template paramter being a " + "%select{type|non-type|template}4 template parameter|" + "function template %2 with %ordinal3 template parameter " + "%select{with no name|named %5}4|" + "function template %2 with %ordinal3 template parameter with " + "%select{no |}4default argument|" + "function template %2 with %ordinal3 template parameter with " + "default argument %4|" + "function template %2 with %ordinal3 template parameter with different type|" + "function template %2 with %ordinal3 template parameter %select{not |}4" + "being a template parameter pack|" "}1">; def err_module_odr_violation_function : Error< Modified: cfe/trunk/lib/AST/ODRHash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=333486&r1=333485&r2=333486&view=diff ============================================================================== --- cfe/trunk/lib/AST/ODRHash.cpp (original) +++ cfe/trunk/lib/AST/ODRHash.cpp Tue May 29 18:12:26 2018 @@ -383,6 +383,7 @@ public: if (hasDefaultArgument) { AddTemplateArgument(D->getDefaultArgument()); } + Hash.AddBoolean(D->isParameterPack()); Inherited::VisitTemplateTypeParmDecl(D); } @@ -395,6 +396,7 @@ public: if (hasDefaultArgument) { AddStmt(D->getDefaultArgument()); } + Hash.AddBoolean(D->isParameterPack()); Inherited::VisitNonTypeTemplateParmDecl(D); } @@ -407,9 +409,27 @@ public: if (hasDefaultArgument) { AddTemplateArgument(D->getDefaultArgument().getArgument()); } + Hash.AddBoolean(D->isParameterPack()); Inherited::VisitTemplateTemplateParmDecl(D); } + + void VisitTemplateDecl(const TemplateDecl *D) { + Hash.AddTemplateParameterList(D->getTemplateParameters()); + + Inherited::VisitTemplateDecl(D); + } + + void VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl *D) { + Hash.AddBoolean(D->isMemberSpecialization()); + Inherited::VisitRedeclarableTemplateDecl(D); + } + + void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { + Visit(D->getTemplatedDecl()); + ID.AddInteger(D->getTemplatedDecl()->getODRHash()); + Inherited::VisitFunctionTemplateDecl(D); + } }; } // namespace @@ -428,6 +448,7 @@ bool ODRHash::isWhitelistedDecl(const De case Decl::CXXMethod: case Decl::Field: case Decl::Friend: + case Decl::FunctionTemplate: case Decl::StaticAssert: case Decl::TypeAlias: case Decl::Typedef: Modified: cfe/trunk/lib/Serialization/ASTReader.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=333486&r1=333485&r2=333486&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue May 29 18:12:26 2018 @@ -9462,6 +9462,14 @@ void ASTReader::diagnoseOdrViolations() return Hash.CalculateHash(); }; + auto ComputeTemplateParameterListODRHash = + [&Hash](const TemplateParameterList *TPL) { + assert(TPL); + Hash.clear(); + Hash.AddTemplateParameterList(TPL); + return Hash.CalculateHash(); + }; + // Issue any pending ODR-failure diagnostics. for (auto &Merge : OdrMergeFailures) { // If we've already pointed out a specific problem with this class, don't @@ -9814,6 +9822,7 @@ void ASTReader::diagnoseOdrViolations() TypeDef, Var, Friend, + FunctionTemplate, Other } FirstDiffType = Other, SecondDiffType = Other; @@ -9851,6 +9860,8 @@ void ASTReader::diagnoseOdrViolations() return Var; case Decl::Friend: return Friend; + case Decl::FunctionTemplate: + return FunctionTemplate; } }; @@ -9937,7 +9948,7 @@ void ASTReader::diagnoseOdrViolations() // Used with err_module_odr_violation_mismatch_decl_diff and // note_module_odr_violation_mismatch_decl_diff - enum ODRDeclDifference{ + enum ODRDeclDifference { StaticAssertCondition, StaticAssertMessage, StaticAssertOnlyMessage, @@ -9973,6 +9984,13 @@ void ASTReader::diagnoseOdrViolations() FriendTypeFunction, FriendType, FriendFunction, + FunctionTemplateDifferentNumberParameters, + FunctionTemplateParameterDifferentKind, + FunctionTemplateParameterName, + FunctionTemplateParameterSingleDefaultArgument, + FunctionTemplateParameterDifferentDefaultArgument, + FunctionTemplateParameterDifferentType, + FunctionTemplatePackParameter, }; // These lambdas have the common portions of the ODR diagnostics. This @@ -10620,6 +10638,305 @@ void ASTReader::diagnoseOdrViolations() Diagnosed = true; break; } + case FunctionTemplate: { + FunctionTemplateDecl *FirstTemplate = + cast<FunctionTemplateDecl>(FirstDecl); + FunctionTemplateDecl *SecondTemplate = + cast<FunctionTemplateDecl>(SecondDecl); + + TemplateParameterList *FirstTPL = + FirstTemplate->getTemplateParameters(); + TemplateParameterList *SecondTPL = + SecondTemplate->getTemplateParameters(); + + if (FirstTPL->size() != SecondTPL->size()) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateDifferentNumberParameters) + << FirstTemplate << FirstTPL->size(); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateDifferentNumberParameters) + << SecondTemplate << SecondTPL->size(); + + Diagnosed = true; + break; + } + + bool ParameterMismatch = false; + for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) { + NamedDecl *FirstParam = FirstTPL->getParam(i); + NamedDecl *SecondParam = SecondTPL->getParam(i); + + if (FirstParam->getKind() != SecondParam->getKind()) { + enum { + TemplateTypeParameter, + NonTypeTemplateParameter, + TemplateTemplateParameter, + }; + auto GetParamType = [](NamedDecl *D) { + switch (D->getKind()) { + default: + llvm_unreachable("Unexpected template parameter type"); + case Decl::TemplateTypeParm: + return TemplateTypeParameter; + case Decl::NonTypeTemplateParm: + return NonTypeTemplateParameter; + case Decl::TemplateTemplateParm: + return TemplateTemplateParameter; + } + }; + + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentKind) + << FirstTemplate << (i + 1) << GetParamType(FirstParam); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentKind) + << SecondTemplate << (i + 1) << GetParamType(SecondParam); + + ParameterMismatch = true; + break; + } + + if (FirstParam->getName() != SecondParam->getName()) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterName) + << FirstTemplate << (i + 1) << (bool)FirstParam->getIdentifier() + << FirstParam; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterName) + << SecondTemplate << (i + 1) + << (bool)SecondParam->getIdentifier() << SecondParam; + ParameterMismatch = true; + break; + } + + if (isa<TemplateTypeParmDecl>(FirstParam) && + isa<TemplateTypeParmDecl>(SecondParam)) { + TemplateTypeParmDecl *FirstTTPD = + cast<TemplateTypeParmDecl>(FirstParam); + TemplateTypeParmDecl *SecondTTPD = + cast<TemplateTypeParmDecl>(SecondParam); + bool HasFirstDefaultArgument = + FirstTTPD->hasDefaultArgument() && + !FirstTTPD->defaultArgumentWasInherited(); + bool HasSecondDefaultArgument = + SecondTTPD->hasDefaultArgument() && + !SecondTTPD->defaultArgumentWasInherited(); + if (HasFirstDefaultArgument != HasSecondDefaultArgument) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << FirstTemplate << (i + 1) << HasFirstDefaultArgument; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << SecondTemplate << (i + 1) << HasSecondDefaultArgument; + ParameterMismatch = true; + break; + } + + if (HasFirstDefaultArgument && HasSecondDefaultArgument) { + QualType FirstType = FirstTTPD->getDefaultArgument(); + QualType SecondType = SecondTTPD->getDefaultArgument(); + if (ComputeQualTypeODRHash(FirstType) != + ComputeQualTypeODRHash(SecondType)) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << FirstTemplate << (i + 1) << FirstType; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << SecondTemplate << (i + 1) << SecondType; + ParameterMismatch = true; + break; + } + } + + if (FirstTTPD->isParameterPack() != + SecondTTPD->isParameterPack()) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack(); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack(); + ParameterMismatch = true; + break; + } + } + + if (isa<TemplateTemplateParmDecl>(FirstParam) && + isa<TemplateTemplateParmDecl>(SecondParam)) { + TemplateTemplateParmDecl *FirstTTPD = + cast<TemplateTemplateParmDecl>(FirstParam); + TemplateTemplateParmDecl *SecondTTPD = + cast<TemplateTemplateParmDecl>(SecondParam); + + TemplateParameterList *FirstTPL = + FirstTTPD->getTemplateParameters(); + TemplateParameterList *SecondTPL = + SecondTTPD->getTemplateParameters(); + + if (ComputeTemplateParameterListODRHash(FirstTPL) != + ComputeTemplateParameterListODRHash(SecondTPL)) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentType) + << FirstTemplate << (i + 1); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentType) + << SecondTemplate << (i + 1); + ParameterMismatch = true; + break; + } + + bool HasFirstDefaultArgument = + FirstTTPD->hasDefaultArgument() && + !FirstTTPD->defaultArgumentWasInherited(); + bool HasSecondDefaultArgument = + SecondTTPD->hasDefaultArgument() && + !SecondTTPD->defaultArgumentWasInherited(); + if (HasFirstDefaultArgument != HasSecondDefaultArgument) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << FirstTemplate << (i + 1) << HasFirstDefaultArgument; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << SecondTemplate << (i + 1) << HasSecondDefaultArgument; + ParameterMismatch = true; + break; + } + + if (HasFirstDefaultArgument && HasSecondDefaultArgument) { + TemplateArgument FirstTA = + FirstTTPD->getDefaultArgument().getArgument(); + TemplateArgument SecondTA = + SecondTTPD->getDefaultArgument().getArgument(); + if (ComputeTemplateArgumentODRHash(FirstTA) != + ComputeTemplateArgumentODRHash(SecondTA)) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << FirstTemplate << (i + 1) << FirstTA; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << SecondTemplate << (i + 1) << SecondTA; + ParameterMismatch = true; + break; + } + } + + if (FirstTTPD->isParameterPack() != + SecondTTPD->isParameterPack()) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack(); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack(); + ParameterMismatch = true; + break; + } + } + + if (isa<NonTypeTemplateParmDecl>(FirstParam) && + isa<NonTypeTemplateParmDecl>(SecondParam)) { + NonTypeTemplateParmDecl *FirstNTTPD = + cast<NonTypeTemplateParmDecl>(FirstParam); + NonTypeTemplateParmDecl *SecondNTTPD = + cast<NonTypeTemplateParmDecl>(SecondParam); + + QualType FirstType = FirstNTTPD->getType(); + QualType SecondType = SecondNTTPD->getType(); + if (ComputeQualTypeODRHash(FirstType) != + ComputeQualTypeODRHash(SecondType)) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentType) + << FirstTemplate << (i + 1); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentType) + << SecondTemplate << (i + 1); + ParameterMismatch = true; + break; + } + + bool HasFirstDefaultArgument = + FirstNTTPD->hasDefaultArgument() && + !FirstNTTPD->defaultArgumentWasInherited(); + bool HasSecondDefaultArgument = + SecondNTTPD->hasDefaultArgument() && + !SecondNTTPD->defaultArgumentWasInherited(); + if (HasFirstDefaultArgument != HasSecondDefaultArgument) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << FirstTemplate << (i + 1) << HasFirstDefaultArgument; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterSingleDefaultArgument) + << SecondTemplate << (i + 1) << HasSecondDefaultArgument; + ParameterMismatch = true; + break; + } + + if (HasFirstDefaultArgument && HasSecondDefaultArgument) { + Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument(); + Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument(); + if (ComputeODRHash(FirstDefaultArgument) != + ComputeODRHash(SecondDefaultArgument)) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << FirstTemplate << (i + 1) << FirstDefaultArgument; + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplateParameterDifferentDefaultArgument) + << SecondTemplate << (i + 1) << SecondDefaultArgument; + ParameterMismatch = true; + break; + } + } + + if (FirstNTTPD->isParameterPack() != + SecondNTTPD->isParameterPack()) { + ODRDiagError(FirstTemplate->getLocation(), + FirstTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << FirstTemplate << (i + 1) << FirstNTTPD->isParameterPack(); + ODRDiagNote(SecondTemplate->getLocation(), + SecondTemplate->getSourceRange(), + FunctionTemplatePackParameter) + << SecondTemplate << (i + 1) + << SecondNTTPD->isParameterPack(); + ParameterMismatch = true; + break; + } + } + } + + if (ParameterMismatch) { + Diagnosed = true; + break; + } + + break; + } } if (Diagnosed) Modified: cfe/trunk/test/Modules/odr_hash.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=333486&r1=333485&r2=333486&view=diff ============================================================================== --- cfe/trunk/test/Modules/odr_hash.cpp (original) +++ cfe/trunk/test/Modules/odr_hash.cpp Tue May 29 18:12:26 2018 @@ -2510,6 +2510,445 @@ Invalid1 i1; #undef DECLS } // namespace PointersAndReferences +namespace FunctionTemplate { +#if defined(FIRST) +struct S1 { + template <int, int> void foo(); +}; +#elif defined(SECOND) +struct S1 { + template <int> void foo(); +}; +#else +S1 s1; +// expected-error@first.h:* {{'FunctionTemplate::S1::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S1' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'foo' does not match}} +#endif + +#if defined(FIRST) +struct S2 { + template <char> void foo(); +}; +#elif defined(SECOND) +struct S2 { + template <int> void foo(); +}; +#else +S2 s2; +// expected-error@first.h:* {{'FunctionTemplate::S2::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S2' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'foo' does not match}} +#endif + +#if defined(FIRST) +struct S3 { + template <int x> void foo(); +}; +#elif defined(SECOND) +struct S3 { + template <int y> void foo(); +}; +#else +S3 s3; +// expected-error@second.h:* {{'FunctionTemplate::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter named 'y'}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter named 'x'}} +#endif + +#if defined(FIRST) +struct S4 { + template <int x> void foo(); +}; +#elif defined(SECOND) +struct S4 { + template <int x> void bar(); +}; +#else +S4 s4; +// expected-error@first.h:* {{'FunctionTemplate::S4::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S4' in module 'SecondModule'}} +// expected-note@second.h:* {{definition has no member 'foo'}} +#endif + +#if defined(FIRST) +struct S5 { + template <int x> void foo(); +}; +#elif defined(SECOND) +struct S5 { + public: + template <int x> void foo(); +}; +#else +S5 s5; +// expected-error@second.h:* {{'FunctionTemplate::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}} +// expected-note@first.h:* {{but in 'FirstModule' found function template}} +#endif + +#if defined(FIRST) +struct S6 { + template <typename x = int> void foo(); +}; +#elif defined(SECOND) +struct S6 { + template <typename x> void foo(); +}; +#else +S6 s6; +// expected-error@second.h:* {{'FunctionTemplate::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}} +#endif + +#if defined(FIRST) +struct S7 { + template <typename x = void> void foo(); +}; +#elif defined(SECOND) +struct S7 { + template <typename x = int> void foo(); +}; +#else +S7 s7; +// expected-error@second.h:* {{'FunctionTemplate::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'int'}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'void'}} +#endif + +#if defined(FIRST) +template <int> +struct U8 {}; +struct S8 { + template <template<int> class x = U8> void foo(); +}; +#elif defined(SECOND) +template <int> +struct T8 {}; +struct S8{ + template <template<int> class x = T8> void foo(); +}; +#else +S8 s8; +// expected-error@second.h:* {{'FunctionTemplate::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'T8'}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'U8'}} +#endif + +#if defined(FIRST) +template <int> +struct U9 {}; +struct S9 { S9(); + template <template<int> class x = U9> void foo(); +}; +#elif defined(SECOND) +struct S9 { S9(); + template <template<int> class x> void foo(); +}; +#else +S9 s9; +// expected-error@second.h:* {{'FunctionTemplate::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}} +#endif + +#if defined(FIRST) +struct S10 { + template <template<int> class x> void foo(); + template <template<typename> class x> void foo(); +}; +#elif defined(SECOND) +struct S10 { + template <template<typename> class x> void foo(); + template <template<int> class x> void foo(); +}; +#else +S10 s10; +// expected-error@second.h:* {{'FunctionTemplate::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with one type}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with different type}} +#endif + +#if defined(FIRST) +struct S11 { + template <template<int> class x> void foo(); +}; +#elif defined(SECOND) +struct S11 { + template <template<int> class> void foo(); +}; +#else +S11 s11; +// expected-error@second.h:* {{'FunctionTemplate::S11' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no name}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter named 'x'}} +#endif + +#if defined(FIRST) +struct S12 { + template <class> void foo(); + template <class, class> void foo(); +}; +#elif defined(SECOND) +struct S12 { + template <class, class> void foo(); + template <class> void foo(); +}; +#else +S12 s12; +// expected-error@second.h:* {{'FunctionTemplate::S12' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 2 template parameters}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1 template parameter}} +#endif + +#if defined(FIRST) +struct S13 { + template <class = int> void foo(); +}; +#elif defined(SECOND) +struct S13 { + template <class = void> void foo(); +}; +#else +S13 s13; +// expected-error@second.h:* {{'FunctionTemplate::S13' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'void'}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'int'}} +#endif + +#if defined(FIRST) +struct S14 { + template <class = void> void foo(); +}; +#elif defined(SECOND) +struct S14 { + template <class> void foo(); +}; +#else +S14 s14; +// expected-error@second.h:* {{'FunctionTemplate::S14' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}} +#endif + +#if defined(FIRST) +struct S15 { + template <class> void foo(); +}; +#elif defined(SECOND) +struct S15 { + template <class = void> void foo(); +}; +#else +S15 s15; +// expected-error@second.h:* {{'FunctionTemplate::S15' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with no default argument}} +#endif + +#if defined(FIRST) +struct S16 { + template <short> void foo(); +}; +#elif defined(SECOND) +struct S16 { + template <short = 1> void foo(); +}; +#else +S16 s16; +// expected-error@second.h:* {{'FunctionTemplate::S16' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with no default argument}} +#endif + +#if defined(FIRST) +struct S17 { + template <short = 2> void foo(); +}; +#elif defined(SECOND) +struct S17 { + template <short = 1 + 1> void foo(); +}; +#else +S17 s17; +// expected-error@second.h:* {{'FunctionTemplate::S17' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 1 + 1}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 2}} +#endif + +#if defined(FIRST) +struct S18 { + template <short> void foo(); + template <int> void foo(); +}; +#elif defined(SECOND) +struct S18 { + template <int> void foo(); + template <short> void foo(); +}; +#else +S18 s18; +// expected-error@second.h:* {{'FunctionTemplate::S18' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with one type}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with different type}} +#endif + +#if defined(FIRST) +struct S19 { + template <short> void foo(); + template <short...> void foo(); +}; +#elif defined(SECOND) +struct S19 { + template <short...> void foo(); + template <short> void foo(); +}; +#else +S19 s19; +// expected-error@second.h:* {{'FunctionTemplate::S19' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template parameter pack}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter not being a template parameter pack}} +#endif + +#if defined(FIRST) +struct S20 { + template <class> void foo(); + template <class...> void foo(); +}; +#elif defined(SECOND) +struct S20 { + template <class...> void foo(); + template <class> void foo(); +}; +#else +S20 s20; +// expected-error@second.h:* {{'FunctionTemplate::S20' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template parameter pack}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter not being a template parameter pack}} +#endif + +#if defined(FIRST) +struct S21 { + template <template<class> class...> void foo(); + template <template<class> class> void foo(); +}; +#elif defined(SECOND) +struct S21 { + template <template<class> class> void foo(); + template <template<class> class...> void foo(); +}; +#else +S21 s21; +// expected-error@second.h:* {{'FunctionTemplate::S21' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter not being a template parameter pack}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter being a template parameter pack}} +#endif + +#if defined(FIRST) +struct S22 { + template <template<class> class> void foo(); + template <class> void foo(); + template <int> void foo(); +}; +#elif defined(SECOND) +struct S22 { + template <class> void foo(); + template <int> void foo(); + template <template<class> class> void foo(); +}; +#else +S22 s22; +// expected-error@second.h:* {{'FunctionTemplate::S22' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a type template parameter}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a template template parameter}} +#endif + +#if defined(FIRST) +struct S23 { + template <class> void foo(); + template <int> void foo(); + template <template<class> class> void foo(); +}; +#elif defined(SECOND) +struct S23 { + template <int> void foo(); + template <template<class> class> void foo(); + template <class> void foo(); +}; +#else +S23 s23; +// expected-error@second.h:* {{'FunctionTemplate::S23' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a non-type template parameter}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a type template parameter}} +#endif + +#if defined(FIRST) +struct S24 { + template <int> void foo(); + template <template<class> class> void foo(); + template <class> void foo(); +}; +#elif defined(SECOND) +struct S24 { + template <template<class> class> void foo(); + template <class> void foo(); + template <int> void foo(); +}; +#else +S24 s24; +// expected-error@second.h:* {{'FunctionTemplate::S24' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template template parameter}} +// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a non-type template parameter}} +#endif + +#if defined(FIRST) +struct S25 { + template <int> void foo(); +}; +#elif defined(SECOND) +struct S25 { + public: + template <int> void foo(); +}; +#else +S25 s25; +// expected-error@second.h:* {{'FunctionTemplate::S25' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}} +// expected-note@first.h:* {{but in 'FirstModule' found function template}} +#endif + +#define DECLS \ + template <int> \ + void nontype1(); \ + template <int x> \ + void nontype2(); \ + template <int, int> \ + void nontype3(); \ + template <int x = 5> \ + void nontype4(); \ + template <int... x> \ + void nontype5(); \ + \ + template <class> \ + void type1(); \ + template <class x> \ + void type2(); \ + template <class, class> \ + void type3(); \ + template <class x = int> \ + void type4(); \ + template <class... x> \ + void type5(); \ + \ + template <template <int> class> \ + void template1(); \ + template <template <int> class x> \ + void template2(); \ + template <template <int> class, template <int> class> \ + void template3(); \ + template <template <int> class x = U> \ + void template4(); \ + template <template <int> class... x> \ + void template5(); + +#if defined(FIRST) || defined(SECOND) +template<int> +struct U {}; +struct Valid1 { + DECLS +}; +#else +Valid1 v1; +#endif + +#if defined(FIRST) || defined(SECOND) +struct Invalid1 { + DECLS + ACCESS +}; +#else +Invalid1 i1; +// expected-error@second.h:* {{'FunctionTemplate::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}} +// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}} +#endif +#undef DECLS +} // Collection of interesting cases below. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits