Switch the semantic DeclContext for a block-scope declaration of a function or
variable from being the function to being the enclosing namespace scope (in
C++) or the TU (in C). This allows us to fix a selection of related issues
where we would build incorrect redeclaration chains for such declarations, and
fail to notice type mismatches.
Such declarations are put into a new IdentifierNamespace, IDNS_LocalExtern,
which is only found when searching scopes, and not found when searching
DeclContexts. Such a declaration is only made visible in its DeclContext if
there are no non-LocalExtern declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191064 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index dc33f2f..d4f9cc4 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -438,9 +438,9 @@
// declaration (not even to the same value).
//
// C++ [dcl.fct.default]p6:
- // Except for member functions of class templates, the default arguments
- // in a member function definition that appears outside of the class
- // definition are added to the set of default arguments provided by the
+ // Except for member functions of class templates, the default arguments
+ // in a member function definition that appears outside of the class
+ // definition are added to the set of default arguments provided by the
// member function declaration in the class definition.
for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) {
ParmVarDecl *OldParam = Old->getParamDecl(p);
@@ -450,9 +450,18 @@
bool NewParamHasDfl = NewParam->hasDefaultArg();
NamedDecl *ND = Old;
- if (S && !isDeclInScope(ND, New->getDeclContext(), S))
+
+ // 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) &&
+ !New->getDeclContext()->isRecord())
// Ignore default parameters of old decl if they are not in
- // the same scope.
+ // the same scope and this is not an out-of-line definition of
+ // a member function.
OldParamHasDfl = false;
if (OldParamHasDfl && NewParamHasDfl) {
@@ -11486,6 +11495,7 @@
// declared the function in, if we were permitted to, for error recovery.
DC = FunctionContainingLocalClass;
}
+ adjustContextForLocalExternDecl(DC);
// C++ [class.friend]p6:
// A function can be defined in a friend declaration of a class if and