aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-09-09 19:05:14 +0000
committerDouglas Gregor <dgregor@apple.com>2011-09-09 19:05:14 +0000
commite761230ae3751b525cadd8066c74ec278ee4ef57 (patch)
tree459e36d24abbe4c0680f2795203885991b4a6eb6
parent9134294114c15b938f2ff954995d9f00f63dd9d8 (diff)
__module_private__ is inherited by redeclarations of an entity, and
must also be present of the first declaration of that entity. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139384 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td6
-rw-r--r--include/clang/Sema/Sema.h11
-rw-r--r--lib/Parse/ParseDecl.cpp2
-rw-r--r--lib/Parse/ParseDeclCXX.cpp2
-rw-r--r--lib/Sema/SemaDecl.cpp38
-rw-r--r--lib/Sema/SemaDeclCXX.cpp2
-rw-r--r--lib/Sema/SemaTemplate.cpp15
-rw-r--r--test/Modules/module-private.cpp26
8 files changed, 85 insertions, 17 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 568e0a3b6b..846b32ba89 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4716,5 +4716,11 @@ def note_related_result_type_inferred : Note<
}
+let CategoryName = "Modules Issue" in {
+def err_module_private_follows_public : Error<
+ "__module_private__ declaration of %0 follows public declaration">;
+
+}
+
} // end of sema component.
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 4bdf3802aa..3306a0f7f5 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1090,6 +1090,12 @@ public:
IdentifierInfo &ModuleName,
SourceLocation ModuleNameLoc);
+ /// \brief Diagnose that \p New is a module-private redeclaration of
+ /// \p Old.
+ void diagnoseModulePrivateRedeclaration(NamedDecl *New, NamedDecl *Old,
+ SourceLocation ModulePrivateKeyword
+ = SourceLocation());
+
/// Scope actions.
void ActOnPopScope(SourceLocation Loc, Scope *S);
void ActOnTranslationUnitScope(Scope *S);
@@ -1125,7 +1131,7 @@ public:
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr, AccessSpecifier AS,
- bool IsModulePrivate,
+ SourceLocation ModulePrivateLoc,
MultiTemplateParamsArg TemplateParameterLists,
bool &OwnedDecl, bool &IsDependent, bool ScopedEnum,
bool ScopedEnumUsesClassTag, TypeResult UnderlyingType);
@@ -3775,7 +3781,8 @@ public:
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr,
TemplateParameterList *TemplateParams,
- AccessSpecifier AS, bool IsModulePrivate,
+ AccessSpecifier AS,
+ SourceLocation ModulePrivateLoc,
unsigned NumOuterTemplateParamLists,
TemplateParameterList **OuterTemplateParamLists);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 3c692cc577..197e446fd3 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2850,7 +2850,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
unsigned DiagID;
Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
StartLoc, SS, Name, NameLoc, attrs.getList(),
- AS, DS.isModulePrivateSpecified(),
+ AS, DS.getModulePrivateSpecLoc(),
MultiTemplateParamsArg(Actions),
Owned, IsDependent, IsScopedEnum,
IsScopedUsingClassTag, BaseType);
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 63f32d094b..dbdb184d4a 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1193,7 +1193,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Declaration or definition of a class type
TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
SS, Name, NameLoc, attrs.getList(), AS,
- DS.isModulePrivateSpecified(),
+ DS.getModulePrivateSpecLoc(),
TParams, Owned, IsDependent, false,
false, clang::TypeResult());
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 4a7be55366..003be8289f 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1397,7 +1397,9 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
// __module_private__ is propagated to later declarations.
if (Old->isModulePrivate())
New->setModulePrivate();
-
+ else if (New->isModulePrivate())
+ diagnoseModulePrivateRedeclaration(New, Old);
+
if (getLangOptions().Microsoft)
return;
@@ -1966,7 +1968,9 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
// __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
// declarations.
if (New->getNumParams() == Old->getNumParams())
@@ -2152,6 +2156,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// __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.
@@ -7139,7 +7145,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr, AccessSpecifier AS,
- bool IsModulePrivate,
+ SourceLocation ModulePrivateLoc,
MultiTemplateParamsArg TemplateParameterLists,
bool &OwnedDecl, bool &IsDependent,
bool ScopedEnum, bool ScopedEnumUsesClassTag,
@@ -7179,7 +7185,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
SS, Name, NameLoc, Attr,
TemplateParams, AS,
- IsModulePrivate,
+ ModulePrivateLoc,
TemplateParameterLists.size() - 1,
(TemplateParameterList**) TemplateParameterLists.release());
return Result.get();
@@ -7744,9 +7750,13 @@ CreateNewDecl:
if (PrevDecl && PrevDecl->isModulePrivate())
New->setModulePrivate();
- else if (IsModulePrivate)
- New->setModulePrivate();
-
+ else if (ModulePrivateLoc.isValid()) {
+ if (PrevDecl && !PrevDecl->isModulePrivate())
+ diagnoseModulePrivateRedeclaration(New, PrevDecl, ModulePrivateLoc);
+ else
+ New->setModulePrivate();
+ }
+
// If this is a specialization of a member class (of a class template),
// check the specialization.
if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
@@ -9417,6 +9427,20 @@ DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc,
return DeclResult((Decl *)0);
}
+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,
SourceLocation PragmaLoc,
SourceLocation NameLoc) {
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 9ffb7765af..f8c2905316 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -9472,7 +9472,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc,
SS, Name, NameLoc, Attr,
TemplateParams, AS_public,
- /*IsModulePrivate=*/false,
+ /*ModulePrivateLoc=*/SourceLocation(),
TempParamLists.size() - 1,
(TemplateParameterList**) TempParamLists.release()).take();
} else {
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index eb199aced4..4b3f6c45d5 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -811,7 +811,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr,
TemplateParameterList *TemplateParams,
- AccessSpecifier AS, bool IsModulePrivate,
+ AccessSpecifier AS, SourceLocation ModulePrivateLoc,
unsigned NumOuterTemplateParamLists,
TemplateParameterList** OuterTemplateParamLists) {
assert(TemplateParams && TemplateParams->size() > 0 &&
@@ -1002,8 +1002,13 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (PrevClassTemplate && PrevClassTemplate->isModulePrivate()) {
NewTemplate->setModulePrivate();
- } else if (IsModulePrivate)
- 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.
QualType T = NewTemplate->getInjectedClassNameSpecialization();
@@ -4943,7 +4948,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TemplateNameLoc,
Attr,
TemplateParams,
- AS_none, /*IsModulePrivate=*/false,
+ AS_none, /*ModulePrivateLoc=*/SourceLocation(),
TemplateParameterLists.size() - 1,
(TemplateParameterList**) TemplateParameterLists.release());
}
@@ -5978,7 +5983,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
bool IsDependent = false;
Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference,
KWLoc, SS, Name, NameLoc, Attr, AS_none,
- /*IsModulePrivate=*/false,
+ /*ModulePrivateLoc=*/SourceLocation(),
MultiTemplateParamsArg(*this, 0, 0),
Owned, IsDependent, false, false,
TypeResult());
diff --git a/test/Modules/module-private.cpp b/test/Modules/module-private.cpp
index 689abd746a..3ee59c8a9c 100644
--- a/test/Modules/module-private.cpp
+++ b/test/Modules/module-private.cpp
@@ -63,4 +63,30 @@ int test_broken() {
return hidden_var; // expected-error{{use of undeclared identifier 'hidden_var'}}
}
+// Check for private redeclarations of public entities.
+template<typename T>
+class public_class_template; // expected-note{{previous declaration is here}}
+
+template<typename T>
+__module_private__ class public_class_template; // expected-error{{__module_private__ declaration of 'public_class_template' follows public declaration}}
+
+
+typedef int public_typedef; // expected-note{{previous declaration is here}}
+typedef __module_private__ int public_typedef; // expected-error{{__module_private__ declaration of 'public_typedef' follows public declaration}}
+
+extern int public_var; // expected-note{{previous declaration is here}}
+extern __module_private__ int public_var; // expected-error{{__module_private__ declaration of 'public_var' follows public declaration}}
+
+void public_func(); // expected-note{{previous declaration is here}}
+__module_private__ void public_func(); // expected-error{{__module_private__ declaration of 'public_func' follows public declaration}}
+
+template<typename T>
+void public_func_template(); // expected-note{{previous declaration is here}}
+template<typename T>
+__module_private__ void public_func_template(); // expected-error{{__module_private__ declaration of 'public_func_template' follows public declaration}}
+
+struct public_struct; // expected-note{{previous declaration is here}}
+__module_private__ struct public_struct; // expected-error{{__module_private__ declaration of 'public_struct' follows public declaration}}
+
+
#endif