forked from OSchip/llvm-project
parent
8737f0650c
commit
ac6a1b6417
|
@ -127,11 +127,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}3">;
|
||||
"data member|friend declaration}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}1">;
|
||||
"data member|friend declaration}1">;
|
||||
|
||||
def err_module_odr_violation_mismatch_decl_diff : Error<
|
||||
"%q0 has different definitions in different modules; first difference is "
|
||||
|
@ -166,6 +166,9 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
|
|||
"data member %4 with%select{out|}5 an initializer|"
|
||||
"data member %4 with an initializer|"
|
||||
"data member %4 %select{is constexpr|is not constexpr}5|"
|
||||
"friend %select{class|function}4|"
|
||||
"friend %4|"
|
||||
"friend function %4|"
|
||||
"}3">;
|
||||
|
||||
def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
|
||||
|
@ -199,18 +202,21 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
|
|||
"data member %2 with%select{out|}3 an initializer|"
|
||||
"data member %2 with a different initializer|"
|
||||
"data member %2 %select{is constexpr|is not constexpr}3|"
|
||||
"friend %select{class|function}2|"
|
||||
"friend %2|"
|
||||
"friend function %2|"
|
||||
"}1">;
|
||||
|
||||
def err_module_odr_violation_mismatch_decl_unknown : Error<
|
||||
"%q0 %select{with definition in module '%2'|defined here}1 has different "
|
||||
"definitions in different modules; first difference is this "
|
||||
"%select{||||static assert|field|method|type alias|typedef|data member|"
|
||||
"unexpected decl}3">;
|
||||
"friend declaration|unexpected decl}3">;
|
||||
def note_module_odr_violation_mismatch_decl_unknown : Note<
|
||||
"but in '%0' found "
|
||||
"%select{||||different static assert|different field|different method|"
|
||||
"different type alias|different typedef|different data member|"
|
||||
"another unexpected decl}1">;
|
||||
"different friend declaration|another unexpected decl}1">;
|
||||
|
||||
def warn_duplicate_module_file_extension : Warning<
|
||||
"duplicate module file extension block name '%0'">,
|
||||
|
|
|
@ -228,6 +228,13 @@ public:
|
|||
Hash.AddQualType(T);
|
||||
}
|
||||
|
||||
void AddDecl(const Decl *D) {
|
||||
Hash.AddBoolean(D);
|
||||
if (D) {
|
||||
Hash.AddDecl(D);
|
||||
}
|
||||
}
|
||||
|
||||
void Visit(const Decl *D) {
|
||||
ID.AddInteger(D->getKind());
|
||||
Inherited::Visit(D);
|
||||
|
@ -321,6 +328,16 @@ public:
|
|||
void VisitTypeAliasDecl(const TypeAliasDecl *D) {
|
||||
Inherited::VisitTypeAliasDecl(D);
|
||||
}
|
||||
|
||||
void VisitFriendDecl(const FriendDecl *D) {
|
||||
TypeSourceInfo *TSI = D->getFriendType();
|
||||
Hash.AddBoolean(TSI);
|
||||
if (TSI) {
|
||||
AddQualType(TSI->getType());
|
||||
} else {
|
||||
AddDecl(D->getFriendDecl());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Only allow a small portion of Decl's to be processed. Remove this once
|
||||
|
@ -335,6 +352,7 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) {
|
|||
case Decl::AccessSpec:
|
||||
case Decl::CXXMethod:
|
||||
case Decl::Field:
|
||||
case Decl::Friend:
|
||||
case Decl::StaticAssert:
|
||||
case Decl::TypeAlias:
|
||||
case Decl::Typedef:
|
||||
|
|
|
@ -9314,6 +9314,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
TypeAlias,
|
||||
TypeDef,
|
||||
Var,
|
||||
Friend,
|
||||
Other
|
||||
} FirstDiffType = Other,
|
||||
SecondDiffType = Other;
|
||||
|
@ -9347,6 +9348,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
return TypeDef;
|
||||
case Decl::Var:
|
||||
return Var;
|
||||
case Decl::Friend:
|
||||
return Friend;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -9463,6 +9466,9 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
VarSingleInitializer,
|
||||
VarDifferentInitializer,
|
||||
VarConstexpr,
|
||||
FriendTypeFunction,
|
||||
FriendType,
|
||||
FriendFunction,
|
||||
};
|
||||
|
||||
// These lambdas have the common portions of the ODR diagnostics. This
|
||||
|
@ -9973,6 +9979,53 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case Friend: {
|
||||
FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl);
|
||||
FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl);
|
||||
|
||||
NamedDecl *FirstND = FirstFriend->getFriendDecl();
|
||||
NamedDecl *SecondND = SecondFriend->getFriendDecl();
|
||||
|
||||
TypeSourceInfo *FirstTSI = FirstFriend->getFriendType();
|
||||
TypeSourceInfo *SecondTSI = SecondFriend->getFriendType();
|
||||
|
||||
if (FirstND && SecondND) {
|
||||
ODRDiagError(FirstFriend->getFriendLoc(),
|
||||
FirstFriend->getSourceRange(), FriendFunction)
|
||||
<< FirstND;
|
||||
ODRDiagNote(SecondFriend->getFriendLoc(),
|
||||
SecondFriend->getSourceRange(), FriendFunction)
|
||||
<< SecondND;
|
||||
|
||||
Diagnosed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FirstTSI && SecondTSI) {
|
||||
QualType FirstFriendType = FirstTSI->getType();
|
||||
QualType SecondFriendType = SecondTSI->getType();
|
||||
assert(ComputeQualTypeODRHash(FirstFriendType) !=
|
||||
ComputeQualTypeODRHash(SecondFriendType));
|
||||
ODRDiagError(FirstFriend->getFriendLoc(),
|
||||
FirstFriend->getSourceRange(), FriendType)
|
||||
<< FirstFriendType;
|
||||
ODRDiagNote(SecondFriend->getFriendLoc(),
|
||||
SecondFriend->getSourceRange(), FriendType)
|
||||
<< SecondFriendType;
|
||||
Diagnosed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
ODRDiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(),
|
||||
FriendTypeFunction)
|
||||
<< (FirstTSI == nullptr);
|
||||
ODRDiagNote(SecondFriend->getFriendLoc(),
|
||||
SecondFriend->getSourceRange(), FriendTypeFunction)
|
||||
<< (SecondTSI == nullptr);
|
||||
|
||||
Diagnosed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Diagnosed == true)
|
||||
|
|
|
@ -1339,6 +1339,84 @@ Bravo<char> golf;
|
|||
#endif
|
||||
}
|
||||
|
||||
namespace Friend {
|
||||
#if defined(FIRST)
|
||||
struct T1 {};
|
||||
struct S1 {
|
||||
friend class T1;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
struct T1 {};
|
||||
struct S1 {
|
||||
friend T1;
|
||||
};
|
||||
#else
|
||||
S1 s1;
|
||||
// expected-error@second.h:* {{'Friend::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend 'Friend::T1'}}
|
||||
// expected-note@first.h:* {{but in 'FirstModule' found friend 'class T1'}}
|
||||
#endif
|
||||
|
||||
#if defined(FIRST)
|
||||
struct T2 {};
|
||||
struct S2 {
|
||||
friend class T2;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
struct T2 {};
|
||||
struct S2 {
|
||||
friend struct T2;
|
||||
};
|
||||
#else
|
||||
S2 s2;
|
||||
// expected-error@second.h:* {{'Friend::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend 'struct T2'}}
|
||||
// expected-note@first.h:* {{but in 'FirstModule' found friend 'class T2'}}
|
||||
#endif
|
||||
|
||||
#if defined(FIRST)
|
||||
struct T3 {};
|
||||
struct S3 {
|
||||
friend const T3;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
struct T3 {};
|
||||
struct S3 {
|
||||
friend T3;
|
||||
};
|
||||
#else
|
||||
S3 s3;
|
||||
// expected-error@second.h:* {{'Friend::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend 'Friend::T3'}}
|
||||
// expected-note@first.h:* {{but in 'FirstModule' found friend 'const Friend::T3'}}
|
||||
#endif
|
||||
|
||||
#if defined(FIRST)
|
||||
struct T4 {};
|
||||
struct S4 {
|
||||
friend T4;
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
struct S4 {
|
||||
friend void T4();
|
||||
};
|
||||
#else
|
||||
S4 s4;
|
||||
// expected-error@second.h:* {{'Friend::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend function}}
|
||||
// expected-note@first.h:* {{but in 'FirstModule' found friend class}}
|
||||
#endif
|
||||
|
||||
#if defined(FIRST)
|
||||
struct S5 {
|
||||
friend void T5a();
|
||||
};
|
||||
#elif defined(SECOND)
|
||||
struct S5 {
|
||||
friend void T5b();
|
||||
};
|
||||
#else
|
||||
S5 s5;
|
||||
// expected-error@second.h:* {{'Friend::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend function 'T5b'}}
|
||||
// expected-note@first.h:* {{but in 'FirstModule' found friend function 'T5a'}}
|
||||
#endif
|
||||
}
|
||||
// Interesting cases that should not cause errors. struct S should not error
|
||||
// while struct T should error at the access specifier mismatch at the end.
|
||||
namespace AllDecls {
|
||||
|
|
Loading…
Reference in New Issue