r333486 - [ODRHash] Support FunctionTemplateDecl in records.
Richard Trieu via cfe-commits
cfe-commits at lists.llvm.org
Tue May 29 18:12:26 PDT 2018
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 at first.h:* {{'FunctionTemplate::S1::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S1' in module 'SecondModule'}}
+// expected-note at 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 at first.h:* {{'FunctionTemplate::S2::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S2' in module 'SecondModule'}}
+// expected-note at 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 at 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 at 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 at first.h:* {{'FunctionTemplate::S4::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S4' in module 'SecondModule'}}
+// expected-note at 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 at second.h:* {{'FunctionTemplate::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
+// expected-note at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at second.h:* {{'FunctionTemplate::S25' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
+// expected-note at 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 at second.h:* {{'FunctionTemplate::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
+// expected-note at first.h:* {{but in 'FirstModule' found public access specifier}}
+#endif
+#undef DECLS
+}
// Collection of interesting cases below.
More information about the cfe-commits
mailing list