diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-02-06 01:31:33 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-02-06 01:31:33 +0000 |
commit | 18819307d302269cd52cbaa5c5ef2ab60dc871d3 (patch) | |
tree | 76938a0f051a01755a68c222b717f103c9559acc /clang/lib/Sema/SemaDecl.cpp | |
parent | d6b107136a54e1fb33f9a888bb6d8c5eec0eb5c2 (diff) | |
download | bcm5719-llvm-18819307d302269cd52cbaa5c5ef2ab60dc871d3.tar.gz bcm5719-llvm-18819307d302269cd52cbaa5c5ef2ab60dc871d3.zip |
DR101, PR12770: If a function is declared in the same context as a
using-declaration, and they declare the same function (either because
the using-declaration is in the same namespace as the declaration it
imports, or because they're both extern "C"), they do not conflict.
llvm-svn: 200897
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. |