diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2012-12-28 14:21:58 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2012-12-28 14:21:58 +0000 |
commit | 78eeba8c7d53b6b2983c76b77b23b45b89ed939d (patch) | |
tree | aa97877589a2d614de6a73c771e1168b78f13909 /lib/Sema | |
parent | ceb59d91b3a7def4297ec8468621805777741963 (diff) |
Reject overloading of two static extern C functions.
This patch moves hasCLanguageLinkage to be VarDecl and FunctionDecl methods
so that they can be used from SemaOverload.cpp and then fixes the logic
in Sema::IsOverload.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@171193 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 30 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 10 |
2 files changed, 11 insertions, 29 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7c193e13bd..c9d0c7750c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1969,32 +1969,6 @@ static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) { return ABIDefaultCC == CC; } -/// Check if the given decl has C language linkage. Note that this is not -/// the same as D.isExternC() since decls with non external linkage can have C -/// language linkage. They can also have C language linkage when they are -/// not declared in an extern C context, but a previous decl is. -template<typename T> -bool hasCLanguageLinkage(const T &D) { - // Language linkage is a C++ concept, but saying that everything in C has - // C language linkage fits the implementation nicelly. - ASTContext &Context = D.getASTContext(); - if (!Context.getLangOpts().CPlusPlus) - return true; - - // dcl.link 4: A C language linkage is ignored in determining the language - // linkage of the names of class members and the function type of class member - // functions. - const DeclContext *DC = D.getDeclContext(); - if (DC->isRecord()) - return false; - - // If the first decl is in an extern "C" context, any other redeclaration - // will have C language linkage. If the first one is not in an extern "C" - // context, we would have reported an error for any other decl being in one. - const T *First = D.getFirstDeclaration(); - return First->getDeclContext()->isExternCContext(); -} - /// 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, @@ -2255,7 +2229,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { assert(OldQTypeForComparison.isCanonical()); } - if (!hasCLanguageLinkage(*Old) && hasCLanguageLinkage(*New)) { + if (!Old->hasCLanguageLinkage() && New->hasCLanguageLinkage()) { Diag(New->getLocation(), diag::err_different_language_linkage) << New; Diag(Old->getLocation(), PrevDiag); return true; @@ -2645,7 +2619,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { return; } - if (!hasCLanguageLinkage(*Old) && hasCLanguageLinkage(*New)) { + if (!Old->hasCLanguageLinkage() && New->hasCLanguageLinkage()) { Diag(New->getLocation(), diag::err_different_language_linkage) << New; Diag(Old->getLocation(), diag::note_previous_definition); New->setInvalidDecl(); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7ae6d9d5af..02584525c9 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -930,11 +930,19 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, return Ovl_Overload; } +static bool canBeOverloaded(const FunctionDecl &D) { + if (D.getAttr<OverloadableAttr>()) + return true; + if (D.hasCLanguageLinkage()) + return false; + return true; +} + bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, bool UseUsingDeclRules) { // If both of the functions are extern "C", then they are not // overloads. - if (Old->isExternC() && New->isExternC()) + if (!canBeOverloaded(*Old) && !canBeOverloaded(*New)) return false; FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); |