r237814 - [modules] Support merging a parsed default function/template argument with an imported but hidden one.
Richard Smith
richard-llvm at metafoo.co.uk
Wed May 20 10:50:35 PDT 2015
Author: rsmith
Date: Wed May 20 12:50:35 2015
New Revision: 237814
URL: http://llvm.org/viewvc/llvm-project?rev=237814&view=rev
Log:
[modules] Support merging a parsed default function/template argument with an imported but hidden one.
Modified:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaLookup.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=237814&r1=237813&r2=237814&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed May 20 12:50:35 2015
@@ -438,6 +438,45 @@ bool Sema::MergeCXXFunctionDecl(Function
Scope *S) {
bool Invalid = false;
+ // 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->isLocalExternDecl()
+ ? New->getLexicalDeclContext()
+ : New->getDeclContext();
+
+ // Find the previous declaration for the purpose of default arguments.
+ FunctionDecl *PrevForDefaultArgs = Old;
+ for (/**/; PrevForDefaultArgs;
+ // Don't bother looking back past the latest decl if this is a local
+ // extern declaration; nothing else could work.
+ PrevForDefaultArgs = New->isLocalExternDecl()
+ ? nullptr
+ : PrevForDefaultArgs->getPreviousDecl()) {
+ // Ignore hidden declarations.
+ if (!LookupResult::isVisible(*this, PrevForDefaultArgs))
+ continue;
+
+ if (S && !isDeclInScope(PrevForDefaultArgs, ScopeDC, S) &&
+ !New->isCXXClassMember()) {
+ // Ignore default arguments of old decl if they are not in
+ // the same scope and this is not an out-of-line definition of
+ // a member function.
+ continue;
+ }
+
+ if (PrevForDefaultArgs->isLocalExternDecl() != New->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.)
+ continue;
+ }
+
+ // We found our guy.
+ break;
+ }
+
// C++ [dcl.fct.default]p4:
// For non-template functions, default arguments can be added in
// later declarations of a function in the same
@@ -456,34 +495,17 @@ bool Sema::MergeCXXFunctionDecl(Function
// 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);
+ for (unsigned p = 0, NumParams = PrevForDefaultArgs
+ ? PrevForDefaultArgs->getNumParams()
+ : 0;
+ p < NumParams; ++p) {
+ ParmVarDecl *OldParam = PrevForDefaultArgs->getParamDecl(p);
ParmVarDecl *NewParam = New->getParamDecl(p);
- bool OldParamHasDfl = OldParam->hasDefaultArg();
+ bool OldParamHasDfl = OldParam ? OldParam->hasDefaultArg() : false;
bool NewParamHasDfl = NewParam->hasDefaultArg();
- // 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->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) {
-
unsigned DiagDefaultParamID =
diag::err_param_default_argument_redefinition;
@@ -491,7 +513,7 @@ bool Sema::MergeCXXFunctionDecl(Function
// of template class. The new default parameter's value is ignored.
Invalid = true;
if (getLangOpts().MicrosoftExt) {
- CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(New);
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(New);
if (MD && MD->getParent()->getDescribedClassTemplate()) {
// Merge the old default argument into the new parameter.
NewParam->setHasInheritedDefaultArg();
@@ -518,7 +540,8 @@ bool Sema::MergeCXXFunctionDecl(Function
// Look for the function declaration where the default argument was
// actually written, which may be a declaration prior to Old.
- for (auto Older = Old; OldParam->hasInheritedDefaultArg();) {
+ for (auto Older = PrevForDefaultArgs;
+ OldParam->hasInheritedDefaultArg(); /**/) {
Older = Older->getPreviousDecl();
OldParam = Older->getParamDecl(p);
}
@@ -543,8 +566,9 @@ bool Sema::MergeCXXFunctionDecl(Function
Diag(NewParam->getLocation(),
diag::err_param_default_argument_template_redecl)
<< NewParam->getDefaultArgRange();
- Diag(Old->getLocation(), diag::note_template_prev_declaration)
- << false;
+ Diag(PrevForDefaultArgs->getLocation(),
+ diag::note_template_prev_declaration)
+ << false;
} else if (New->getTemplateSpecializationKind()
!= TSK_ImplicitInstantiation &&
New->getTemplateSpecializationKind() != TSK_Undeclared) {
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=237814&r1=237813&r2=237814&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed May 20 12:50:35 2015
@@ -1304,7 +1304,12 @@ bool LookupResult::isVisibleSlow(Sema &S
DeclContext *DC = D->getLexicalDeclContext();
if (!D->isModulePrivate() &&
DC && !DC->isFileContext() && !isa<LinkageSpecDecl>(DC)) {
- if (SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC))) {
+ // For a parameter, check whether our current template declaration's
+ // lexical context is visible, not whether there's some other visible
+ // definition of it, because parameters aren't "within" the definition.
+ if ((D->isTemplateParameter() || isa<ParmVarDecl>(D))
+ ? isVisible(SemaRef, cast<NamedDecl>(DC))
+ : SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC))) {
if (SemaRef.ActiveTemplateInstantiations.empty() &&
// FIXME: Do something better in this case.
!SemaRef.getLangOpts().ModulesLocalVisibility) {
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=237814&r1=237813&r2=237814&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed May 20 12:50:35 2015
@@ -1310,6 +1310,9 @@ bool Sema::CheckTemplateParameterList(Te
// Merge default arguments for template type parameters.
TemplateTypeParmDecl *OldTypeParm
= OldParams? cast<TemplateTypeParmDecl>(*OldParam) : nullptr;
+ // FIXME: There might be a visible declaration of this template parameter.
+ if (OldTypeParm && !LookupResult::isVisible(*this, OldTypeParm))
+ OldTypeParm = nullptr;
if (NewTypeParm->isParameterPack()) {
assert(!NewTypeParm->hasDefaultArgument() &&
Modified: cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h?rev=237814&r1=237813&r2=237814&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h (original)
+++ cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h Wed May 20 12:50:35 2015
@@ -43,3 +43,5 @@ namespace G {
typedef enum { i, j } k;
typedef enum {} l;
}
+
+template<typename T = int> int H(int a = 1);
More information about the cfe-commits
mailing list