aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-02-14 01:18:37 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-02-14 01:18:37 +0000
commit950fee2555f7a6bd193e588d6b6a941fd182391a (patch)
treea0dd9afcad02780d91902e9510ea41187947662d /lib/Sema/SemaDecl.cpp
parentd3b4f0e27ffa8d73f8c69a717c39c39a4d47ff0c (diff)
Add a getLanguageLinkage method to VarDecls and FunctionDecls. Use it to fix
some cases where functions with no language linkage were being treated as having C language linkage. In particular, don't warn in extern "C" { static NonPod foo(); } Since getLanguageLinkage checks the language linkage, the linkage computation cannot use the language linkage. Break the loop by checking just the context in the linkage computation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175117 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp20
1 files changed, 18 insertions, 2 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 7c31be6c13..9c7fb6b4b2 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2065,6 +2065,22 @@ static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) {
return ABIDefaultCC == CC;
}
+template<typename T>
+bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
+ const DeclContext *DC = Old->getDeclContext();
+ if (DC->isRecord())
+ return false;
+
+ LanguageLinkage OldLinkage = Old->getLanguageLinkage();
+ if (OldLinkage == CXXLanguageLinkage &&
+ New->getDeclContext()->isExternCContext())
+ return true;
+ if (OldLinkage == CLanguageLinkage &&
+ New->getDeclContext()->isExternCXXContext())
+ return true;
+ return false;
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -2366,7 +2382,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
assert(OldQTypeForComparison.isCanonical());
}
- if (!Old->hasCLanguageLinkage() && New->hasCLanguageLinkage()) {
+ if (haveIncompatibleLanguageLinkages(Old, New)) {
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
Diag(Old->getLocation(), PrevDiag);
return true;
@@ -2756,7 +2772,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
return;
}
- if (!Old->hasCLanguageLinkage() && New->hasCLanguageLinkage()) {
+ if (haveIncompatibleLanguageLinkages(Old, New)) {
Diag(New->getLocation(), diag::err_different_language_linkage) << New;
Diag(Old->getLocation(), diag::note_previous_definition);
New->setInvalidDecl();