From: Richard Smith Date: Wed, 27 Aug 2014 22:31:34 +0000 (+0000) Subject: PR20769: Fix confusion when checking whether a prior default argument was in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f1967c99fdc9d5d816fe173295915d012410bbf3;p=clang PR20769: Fix confusion when checking whether a prior default argument was in scope when checking for conflicts. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216628 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index 2a5bacff0d..6586fb3278 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -130,6 +130,9 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S, return false; } + // FIXME: If D is a local extern declaration, this check doesn't make sense; + // we should be checking its lexical context instead in that case, because + // that is its scope. DeclContext *DCtx = D->getDeclContext()->getRedeclContext(); return AllowInlineNamespace ? Ctx->InEnclosingNamespaceSetOf(DCtx) : Ctx->Equals(DCtx); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 081d91e050..f0925e478b 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -446,20 +446,24 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, bool OldParamHasDfl = OldParam->hasDefaultArg(); bool NewParamHasDfl = NewParam->hasDefaultArg(); - NamedDecl *ND = Old; - // The declaration context corresponding to the scope is the semantic // parent, unless this is a local function declaration, in which case // it is that surrounding function. - DeclContext *ScopeDC = New->getLexicalDeclContext(); - if (!ScopeDC->isFunctionOrMethod()) - ScopeDC = New->getDeclContext(); - if (S && !isDeclInScope(ND, ScopeDC, S) && + DeclContext *ScopeDC = New->isLocalExternDecl() + ? New->getLexicalDeclContext() + : New->getDeclContext(); + if (S && !isDeclInScope(Old, ScopeDC, S) && !New->getDeclContext()->isRecord()) // Ignore default parameters of old decl if they are not in // the same scope and this is not an out-of-line definition of // a member function. OldParamHasDfl = false; + if (New->isLocalExternDecl() != Old->isLocalExternDecl()) + // If only one of these is a local function declaration, then they are + // declared in different scopes, even though isDeclInScope may think + // they're in the same scope. (If both are local, the scope check is + // sufficent, and if neither is local, then they are in the same scope.) + OldParamHasDfl = false; if (OldParamHasDfl && NewParamHasDfl) { diff --git a/test/SemaCXX/default1.cpp b/test/SemaCXX/default1.cpp index 23466fac62..6001001b11 100644 --- a/test/SemaCXX/default1.cpp +++ b/test/SemaCXX/default1.cpp @@ -65,3 +65,9 @@ int i2() { int pr20055_f(int x = 0, int y = UNDEFINED); // expected-error{{use of undeclared identifier}} int pr20055_v = pr20055_f(0); + +void PR20769() { void PR20769(int = 1); } +void PR20769(int = 2); + +void PR20769_b(int = 1); +void PR20769_b() { void PR20769_b(int = 2); }