summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorAlp Toker <alp@nuanti.com>2013-10-22 22:53:01 +0000
committerAlp Toker <alp@nuanti.com>2013-10-22 22:53:01 +0000
commitdd551fc3ae9d32a0c5528c07b3ec183224bfb061 (patch)
treea6a269c3f38028c6fd1d632ba287ac452940f51e /clang/lib/Sema/SemaDecl.cpp
parent6b53e224ebcd0b99be4db9fc12e9d080c69c04b9 (diff)
downloadbcm5719-llvm-dd551fc3ae9d32a0c5528c07b3ec183224bfb061.tar.gz
bcm5719-llvm-dd551fc3ae9d32a0c5528c07b3ec183224bfb061.zip
Retain previous language linkage of friend function declarations
With this extension, friend function declarations will retain the language linkage specified for previous declarations instead of emitting an error diagnostic. The feature is known to be compatible with GCC and MSVC and permits a language to be specified indirectly where it cannot otherwise be written directly in class scope. Work is ongoing to improve linkage spec diagnostics. Fixes PR17337. Reviewed by Richard Smith. llvm-svn: 193206
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp19
1 files changed, 16 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 81ade1f3ce0..80f95e68690 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2607,9 +2607,22 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
}
if (haveIncompatibleLanguageLinkages(Old, New)) {
- Diag(New->getLocation(), diag::err_different_language_linkage) << New;
- Diag(Old->getLocation(), PrevDiag);
- return true;
+ // As a special case, retain the language linkage from previous
+ // declarations of a friend function as an extension.
+ //
+ // This liberal interpretation of C++ [class.friend]p3 matches GCC/MSVC
+ // and is useful because there's otherwise no way to specify language
+ // linkage within class scope.
+ //
+ // Check cautiously as the friend object kind isn't yet complete.
+ if (New->getFriendObjectKind() != Decl::FOK_None) {
+ Diag(New->getLocation(), diag::ext_retained_language_linkage) << New;
+ Diag(Old->getLocation(), PrevDiag);
+ } else {
+ Diag(New->getLocation(), diag::err_different_language_linkage) << New;
+ Diag(Old->getLocation(), PrevDiag);
+ return true;
+ }
}
if (OldQTypeForComparison == NewQType)
OpenPOWER on IntegriCloud