diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 995898aea48..8b750812d9c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2268,8 +2268,8 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) { /// merged with. /// /// Returns true if there was an error, false otherwise. -bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, - bool MergeTypeWithOld) { +bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, + Scope *S, bool MergeTypeWithOld) { // Verify the old decl was also a function. FunctionDecl *Old = OldD->getAsFunction(); if (!Old) { @@ -2283,18 +2283,34 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, return true; } - Diag(New->getLocation(), diag::err_using_decl_conflict_reverse); - Diag(Shadow->getTargetDecl()->getLocation(), - diag::note_using_decl_target); - Diag(Shadow->getUsingDecl()->getLocation(), - diag::note_using_decl) << 0; + // C++11 [namespace.udecl]p14: + // If a function declaration in namespace scope or block scope has the + // same name and the same parameter-type-list as a function introduced + // by a using-declaration, and the declarations do not declare the same + // function, the program is ill-formed. + + // Check whether the two declarations might declare the same function. + Old = dyn_cast<FunctionDecl>(Shadow->getTargetDecl()); + if (Old && + !Old->getDeclContext()->getRedeclContext()->Equals( + New->getDeclContext()->getRedeclContext()) && + !(Old->isExternC() && New->isExternC())) + Old = 0; + + if (!Old) { + Diag(New->getLocation(), diag::err_using_decl_conflict_reverse); + Diag(Shadow->getTargetDecl()->getLocation(), + diag::note_using_decl_target); + Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0; + return true; + } + OldD = Old; + } else { + Diag(New->getLocation(), diag::err_redefinition_different_kind) + << New->getDeclName(); + Diag(OldD->getLocation(), diag::note_previous_definition); return true; } - - Diag(New->getLocation(), diag::err_redefinition_different_kind) - << New->getDeclName(); - Diag(OldD->getLocation(), diag::note_previous_definition); - return true; } // If the old declaration is invalid, just give up here. |