When performing name lookup for a redeclaration, ignore module
visibility restrictions. This ensures that all declarations of the same entity end up in the same redeclaration chain, even if some of those declarations aren't visible. While this may seem unfortunate to some---why can't two C modules have different functions named 'f'?---it's an acknowedgment that a module does not introduce a new "namespace" of names. As part of this, stop merging the 'module-private' bit from previous declarations to later declarations, because we want each declaration in a module to stand on its own because this can effect, for example, submodule visibility. Note that this notion of names that are invisible to normal name lookup but are available for redeclaration lookups is how we should implement friend declarations and extern declarations within local function scopes. I'm not tackling that problem now. llvm-svn: 146980
This commit is contained in:
parent
9735fc9abd
commit
21823bfe31
|
@ -5154,8 +5154,6 @@ def note_related_result_type_inferred : Note<
|
||||||
}
|
}
|
||||||
|
|
||||||
let CategoryName = "Modules Issue" in {
|
let CategoryName = "Modules Issue" in {
|
||||||
def err_module_private_follows_public : Error<
|
|
||||||
"__module_private__ declaration of %0 follows public declaration">;
|
|
||||||
def err_module_private_specialization : Error<
|
def err_module_private_specialization : Error<
|
||||||
"%select{template|partial|member}0 specialization cannot be "
|
"%select{template|partial|member}0 specialization cannot be "
|
||||||
"declared __module_private__">;
|
"declared __module_private__">;
|
||||||
|
|
|
@ -286,7 +286,7 @@ public:
|
||||||
if (!D->isInIdentifierNamespace(IDNS))
|
if (!D->isInIdentifierNamespace(IDNS))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (isVisible(D))
|
if (Redecl == Sema::ForRedeclaration || isVisible(D))
|
||||||
return D;
|
return D;
|
||||||
|
|
||||||
return getAcceptableDeclSlow(D);
|
return getAcceptableDeclSlow(D);
|
||||||
|
|
|
@ -1119,12 +1119,6 @@ public:
|
||||||
/// \param Path The module access path.
|
/// \param Path The module access path.
|
||||||
DeclResult ActOnModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
|
DeclResult ActOnModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
|
||||||
|
|
||||||
/// \brief Diagnose that \p New is a module-private redeclaration of
|
|
||||||
/// \p Old.
|
|
||||||
void diagnoseModulePrivateRedeclaration(NamedDecl *New, NamedDecl *Old,
|
|
||||||
SourceLocation ModulePrivateKeyword
|
|
||||||
= SourceLocation());
|
|
||||||
|
|
||||||
/// \brief Retrieve a suitable printing policy.
|
/// \brief Retrieve a suitable printing policy.
|
||||||
PrintingPolicy getPrintingPolicy() const;
|
PrintingPolicy getPrintingPolicy() const;
|
||||||
|
|
||||||
|
|
|
@ -1456,12 +1456,6 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
|
||||||
if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old))
|
if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old))
|
||||||
New->setPreviousDeclaration(Typedef);
|
New->setPreviousDeclaration(Typedef);
|
||||||
|
|
||||||
// __module_private__ is propagated to later declarations.
|
|
||||||
if (Old->isModulePrivate())
|
|
||||||
New->setModulePrivate();
|
|
||||||
else if (New->isModulePrivate())
|
|
||||||
diagnoseModulePrivateRedeclaration(New, Old);
|
|
||||||
|
|
||||||
if (getLangOptions().MicrosoftExt)
|
if (getLangOptions().MicrosoftExt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2047,12 +2041,6 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
|
||||||
if (Old->isPure())
|
if (Old->isPure())
|
||||||
New->setPure();
|
New->setPure();
|
||||||
|
|
||||||
// __module_private__ is propagated to later declarations.
|
|
||||||
if (Old->isModulePrivate())
|
|
||||||
New->setModulePrivate();
|
|
||||||
else if (New->isModulePrivate())
|
|
||||||
diagnoseModulePrivateRedeclaration(New, Old);
|
|
||||||
|
|
||||||
// Merge attributes from the parameters. These can mismatch with K&R
|
// Merge attributes from the parameters. These can mismatch with K&R
|
||||||
// declarations.
|
// declarations.
|
||||||
if (New->getNumParams() == Old->getNumParams())
|
if (New->getNumParams() == Old->getNumParams())
|
||||||
|
@ -2237,12 +2225,6 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
||||||
return New->setInvalidDecl();
|
return New->setInvalidDecl();
|
||||||
}
|
}
|
||||||
|
|
||||||
// __module_private__ is propagated to later declarations.
|
|
||||||
if (Old->isModulePrivate())
|
|
||||||
New->setModulePrivate();
|
|
||||||
else if (New->isModulePrivate())
|
|
||||||
diagnoseModulePrivateRedeclaration(New, Old);
|
|
||||||
|
|
||||||
// Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
|
// Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
|
||||||
|
|
||||||
// FIXME: The test for external storage here seems wrong? We still
|
// FIXME: The test for external storage here seems wrong? We still
|
||||||
|
@ -5627,9 +5609,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||||
assert(OldTemplateDecl->isMemberSpecialization());
|
assert(OldTemplateDecl->isMemberSpecialization());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OldTemplateDecl->isModulePrivate())
|
|
||||||
NewTemplateDecl->setModulePrivate();
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
|
if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
|
||||||
NewFD->setAccess(OldDecl->getAccess());
|
NewFD->setAccess(OldDecl->getAccess());
|
||||||
|
@ -8212,19 +8191,14 @@ CreateNewDecl:
|
||||||
AddMsStructLayoutForRecord(RD);
|
AddMsStructLayoutForRecord(RD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PrevDecl && PrevDecl->isModulePrivate())
|
if (ModulePrivateLoc.isValid()) {
|
||||||
New->setModulePrivate();
|
|
||||||
else if (ModulePrivateLoc.isValid()) {
|
|
||||||
if (isExplicitSpecialization)
|
if (isExplicitSpecialization)
|
||||||
Diag(New->getLocation(), diag::err_module_private_specialization)
|
Diag(New->getLocation(), diag::err_module_private_specialization)
|
||||||
<< 2
|
<< 2
|
||||||
<< FixItHint::CreateRemoval(ModulePrivateLoc);
|
<< FixItHint::CreateRemoval(ModulePrivateLoc);
|
||||||
else if (PrevDecl && !PrevDecl->isModulePrivate())
|
|
||||||
diagnoseModulePrivateRedeclaration(New, PrevDecl, ModulePrivateLoc);
|
|
||||||
// __module_private__ does not apply to local classes. However, we only
|
// __module_private__ does not apply to local classes. However, we only
|
||||||
// diagnose this as an error when the declaration specifiers are
|
// diagnose this as an error when the declaration specifiers are
|
||||||
// freestanding. Here, we just ignore the __module_private__.
|
// freestanding. Here, we just ignore the __module_private__.
|
||||||
// foobar
|
|
||||||
else if (!SearchDC->isFunctionOrMethod())
|
else if (!SearchDC->isFunctionOrMethod())
|
||||||
New->setModulePrivate();
|
New->setModulePrivate();
|
||||||
}
|
}
|
||||||
|
@ -9969,20 +9943,6 @@ DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc, ModuleIdPath Path)
|
||||||
return Import;
|
return Import;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Sema::diagnoseModulePrivateRedeclaration(NamedDecl *New, NamedDecl *Old,
|
|
||||||
SourceLocation ModulePrivateKeyword) {
|
|
||||||
assert(!Old->isModulePrivate() && "Old is module-private!");
|
|
||||||
|
|
||||||
Diag(New->getLocation(), diag::err_module_private_follows_public)
|
|
||||||
<< New->getDeclName() << SourceRange(ModulePrivateKeyword);
|
|
||||||
Diag(Old->getLocation(), diag::note_previous_declaration)
|
|
||||||
<< Old->getDeclName();
|
|
||||||
|
|
||||||
// Drop the __module_private__ from the new declaration, since it's invalid.
|
|
||||||
New->setModulePrivate(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
|
void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
|
||||||
SourceLocation PragmaLoc,
|
SourceLocation PragmaLoc,
|
||||||
SourceLocation NameLoc) {
|
SourceLocation NameLoc) {
|
||||||
|
|
|
@ -1169,7 +1169,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
|
||||||
|
|
||||||
// If this declaration is module-private and it came from an AST
|
// If this declaration is module-private and it came from an AST
|
||||||
// file, we can't see it.
|
// file, we can't see it.
|
||||||
NamedDecl *D = getVisibleDecl(*I);
|
NamedDecl *D = R.isForRedeclaration()? *I : getVisibleDecl(*I);
|
||||||
if (!D)
|
if (!D)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -1013,15 +1013,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||||
NewClass, PrevClassTemplate);
|
NewClass, PrevClassTemplate);
|
||||||
NewClass->setDescribedClassTemplate(NewTemplate);
|
NewClass->setDescribedClassTemplate(NewTemplate);
|
||||||
|
|
||||||
if (PrevClassTemplate && PrevClassTemplate->isModulePrivate()) {
|
if (ModulePrivateLoc.isValid())
|
||||||
NewTemplate->setModulePrivate();
|
NewTemplate->setModulePrivate();
|
||||||
} else if (ModulePrivateLoc.isValid()) {
|
|
||||||
if (PrevClassTemplate && !PrevClassTemplate->isModulePrivate())
|
|
||||||
diagnoseModulePrivateRedeclaration(NewTemplate, PrevClassTemplate,
|
|
||||||
ModulePrivateLoc);
|
|
||||||
else
|
|
||||||
NewTemplate->setModulePrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the type for the class template declaration now.
|
// Build the type for the class template declaration now.
|
||||||
QualType T = NewTemplate->getInjectedClassNameSpecialization();
|
QualType T = NewTemplate->getInjectedClassNameSpecialization();
|
||||||
|
|
|
@ -44,7 +44,8 @@ module decldef {
|
||||||
}
|
}
|
||||||
|
|
||||||
module redecl_merge_top {
|
module redecl_merge_top {
|
||||||
header "redecl-merge-top.h"
|
header "redecl-merge-top.h"
|
||||||
|
explicit module Explicit { header "redecl-merge-top-explicit.h" }
|
||||||
}
|
}
|
||||||
module redecl_merge_left {
|
module redecl_merge_left {
|
||||||
header "redecl-merge-left.h"
|
header "redecl-merge-left.h"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
__module_private__ struct HiddenStruct;
|
__module_private__ struct HiddenStruct;
|
||||||
|
|
||||||
struct HiddenStruct {
|
__module_private__ struct HiddenStruct {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,17 +10,17 @@ template<typename T>
|
||||||
__module_private__ void f1(T*);
|
__module_private__ void f1(T*);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void f1(T*);
|
__module_private__ void f1(T*);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
__module_private__ class vector;
|
__module_private__ class vector;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class vector {
|
__module_private__ class vector {
|
||||||
};
|
};
|
||||||
|
|
||||||
vector<float> vec_float;
|
vector<float> vec_float;
|
||||||
|
|
||||||
typedef __module_private__ int Integer;
|
typedef __module_private__ int Integer;
|
||||||
typedef int Integer;
|
typedef __module_private__ int Integer;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
__module_private__ double &f0(double);
|
__module_private__ double &f0(double);
|
||||||
double &f0(double);
|
__module_private__ double &f0(double);
|
||||||
|
|
||||||
__module_private__ int hidden_var;
|
__module_private__ int hidden_var;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,12 @@ __import_module__ redecl_merge_top;
|
||||||
|
|
||||||
@class A;
|
@class A;
|
||||||
|
|
||||||
|
@class Explicit;
|
||||||
|
|
||||||
|
int *explicit_func(void);
|
||||||
|
|
||||||
|
struct explicit_struct;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
template<typename T> class Vector;
|
template<typename T> class Vector;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,12 @@ __import_module__ redecl_merge_top;
|
||||||
|
|
||||||
@class B;
|
@class B;
|
||||||
|
|
||||||
|
@class Explicit;
|
||||||
|
|
||||||
|
int *explicit_func(void);
|
||||||
|
|
||||||
|
struct explicit_struct;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
template<typename T> class Vector {
|
template<typename T> class Vector {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
@class Explicit;
|
||||||
|
|
||||||
|
int *explicit_func(void);
|
||||||
|
|
||||||
|
struct explicit_struct { int member; };
|
|
@ -31,28 +31,28 @@ int test_broken() {
|
||||||
|
|
||||||
// Check for private redeclarations of public entities.
|
// Check for private redeclarations of public entities.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class public_class_template; // expected-note{{previous declaration is here}}
|
class public_class_template;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
__module_private__ class public_class_template; // expected-error{{__module_private__ declaration of 'public_class_template' follows public declaration}}
|
__module_private__ class public_class_template;
|
||||||
|
|
||||||
|
|
||||||
typedef int public_typedef; // expected-note{{previous declaration is here}}
|
typedef int public_typedef;
|
||||||
typedef __module_private__ int public_typedef; // expected-error{{__module_private__ declaration of 'public_typedef' follows public declaration}}
|
typedef __module_private__ int public_typedef;
|
||||||
|
|
||||||
extern int public_var; // expected-note{{previous declaration is here}}
|
extern int public_var;
|
||||||
extern __module_private__ int public_var; // expected-error{{__module_private__ declaration of 'public_var' follows public declaration}}
|
extern __module_private__ int public_var;
|
||||||
|
|
||||||
void public_func(); // expected-note{{previous declaration is here}}
|
void public_func();
|
||||||
__module_private__ void public_func(); // expected-error{{__module_private__ declaration of 'public_func' follows public declaration}}
|
__module_private__ void public_func();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void public_func_template(); // expected-note{{previous declaration is here}}
|
void public_func_template();
|
||||||
template<typename T>
|
template<typename T>
|
||||||
__module_private__ void public_func_template(); // expected-error{{__module_private__ declaration of 'public_func_template' follows public declaration}}
|
__module_private__ void public_func_template();
|
||||||
|
|
||||||
struct public_struct; // expected-note{{previous declaration is here}}
|
struct public_struct;
|
||||||
__module_private__ struct public_struct; // expected-error{{__module_private__ declaration of 'public_struct' follows public declaration}}
|
__module_private__ struct public_struct;
|
||||||
|
|
||||||
// Check for attempts to make specializations private
|
// Check for attempts to make specializations private
|
||||||
template<> __module_private__ void public_func_template<int>(); // expected-error{{template specialization cannot be declared __module_private__}}
|
template<> __module_private__ void public_func_template<int>(); // expected-error{{template specialization cannot be declared __module_private__}}
|
||||||
|
|
|
@ -20,6 +20,18 @@ B *f1() {
|
||||||
|
|
||||||
@class B;
|
@class B;
|
||||||
|
|
||||||
|
// Test redeclarations of entities in explicit submodules, to make
|
||||||
|
// sure we're maintaining the declaration chains even when normal name
|
||||||
|
// lookup can't see what we're looking for.
|
||||||
|
void testExplicit() {
|
||||||
|
Explicit *e;
|
||||||
|
int *(*fp)(void) = &explicit_func;
|
||||||
|
int *ip = explicit_func();
|
||||||
|
|
||||||
|
// FIXME: Should complain about definition not having been imported.
|
||||||
|
struct explicit_struct es = { 0 };
|
||||||
|
}
|
||||||
|
|
||||||
__import_module__ redecl_merge_bottom;
|
__import_module__ redecl_merge_bottom;
|
||||||
|
|
||||||
@implementation B
|
@implementation B
|
||||||
|
|
Loading…
Reference in New Issue