[cfe-commits] r142468 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/cxx98-compat.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Tue Oct 18 17:54:10 PDT 2011
Author: rsmith
Date: Tue Oct 18 19:54:10 2011
New Revision: 142468
URL: http://llvm.org/viewvc/llvm-project?rev=142468&view=rev
Log:
Add a -Wc++98-compat warning for friend functions of class templates which would
be implicitly instantiated (resulting in a redefinition) in C++98.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaCXX/cxx98-compat.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=142468&r1=142467&r2=142468&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Oct 18 19:54:10 2011
@@ -2652,6 +2652,9 @@
def err_redefinition_extern_inline : Error<
"redefinition of a 'extern inline' function %0 is not supported in "
"%select{C99 mode|C++}1">;
+def warn_cxx98_compat_friend_redefinition : Warning<
+ "friend function %0 would be implicitly redefined in C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
// This should eventually be an error.
def warn_undefined_internal : Warning<
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=142468&r1=142467&r2=142468&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Oct 18 19:54:10 2011
@@ -1230,16 +1230,33 @@
bool queuedInstantiation = false;
- if (!SemaRef.getLangOptions().CPlusPlus0x &&
+ // C++98 [temp.friend]p5: When a function is defined in a friend function
+ // declaration in a class template, the function is defined at each
+ // instantiation of the class template. The function is defined even if it
+ // is never used.
+ // C++11 [temp.friend]p4: When a function is defined in a friend function
+ // declaration in a class template, the function is instantiated when the
+ // function is odr-used.
+ //
+ // If -Wc++98-compat is enabled, we go through the motions of checking for a
+ // redefinition, but don't instantiate the function.
+ if ((!SemaRef.getLangOptions().CPlusPlus0x ||
+ SemaRef.Diags.getDiagnosticLevel(
+ diag::warn_cxx98_compat_friend_redefinition,
+ Function->getLocation())
+ != DiagnosticsEngine::Ignored) &&
D->isThisDeclarationADefinition()) {
// Check for a function body.
const FunctionDecl *Definition = 0;
if (Function->isDefined(Definition) &&
Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
- SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
- << Function->getDeclName();
+ SemaRef.Diag(Function->getLocation(),
+ SemaRef.getLangOptions().CPlusPlus0x ?
+ diag::warn_cxx98_compat_friend_redefinition :
+ diag::err_redefinition) << Function->getDeclName();
SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition);
- Function->setInvalidDecl();
+ if (!SemaRef.getLangOptions().CPlusPlus0x)
+ Function->setInvalidDecl();
}
// Check for redefinitions due to other instantiations of this or
// a similar friend function.
@@ -1250,7 +1267,8 @@
continue;
switch (R->getFriendObjectKind()) {
case Decl::FOK_None:
- if (!queuedInstantiation && R->isUsed(false)) {
+ if (!SemaRef.getLangOptions().CPlusPlus0x &&
+ !queuedInstantiation && R->isUsed(false)) {
if (MemberSpecializationInfo *MSInfo
= Function->getMemberSpecializationInfo()) {
if (MSInfo->getPointOfInstantiation().isInvalid()) {
@@ -1267,10 +1285,14 @@
if (const FunctionDecl *RPattern
= R->getTemplateInstantiationPattern())
if (RPattern->isDefined(RPattern)) {
- SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
+ SemaRef.Diag(Function->getLocation(),
+ SemaRef.getLangOptions().CPlusPlus0x ?
+ diag::warn_cxx98_compat_friend_redefinition :
+ diag::err_redefinition)
<< Function->getDeclName();
SemaRef.Diag(R->getLocation(), diag::note_previous_definition);
- Function->setInvalidDecl();
+ if (!SemaRef.getLangOptions().CPlusPlus0x)
+ Function->setInvalidDecl();
break;
}
}
Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=142468&r1=142467&r2=142468&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Tue Oct 18 19:54:10 2011
@@ -179,3 +179,10 @@
}
int SFINAEAccessControl(...) { return 0; }
int CheckSFINAEAccessControl = SFINAEAccessControl(PrivateMember());
+
+template<typename T>
+struct FriendRedefinition {
+ friend void Friend() {} // expected-warning {{friend function 'Friend' would be implicitly redefined in C++98}} expected-note {{previous}}
+};
+FriendRedefinition<int> FriendRedef1;
+FriendRedefinition<char> FriendRedef2; // expected-note {{requested here}}
More information about the cfe-commits
mailing list