mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-12 02:47:10 +00:00
[ODRHash] Support FunctionTemplateDecl in records.
llvm-svn: 333486
This commit is contained in:
parent
92e523bf55
commit
9359e8f22a
@ -168,11 +168,11 @@ def err_module_odr_violation_mismatch_decl : Error<
|
||||
"%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_decl_diff : Error<
|
||||
"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_decl_diff : Note<"but in '%0' found "
|
||||
"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<
|
||||
|
@ -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 Decl *D, const CXXRecordDecl *Parent) {
|
||||
case Decl::CXXMethod:
|
||||
case Decl::Field:
|
||||
case Decl::Friend:
|
||||
case Decl::FunctionTemplate:
|
||||
case Decl::StaticAssert:
|
||||
case Decl::TypeAlias:
|
||||
case Decl::Typedef:
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user