]> granicus.if.org Git - clang/commitdiff
__module_private__ is inherited by redeclarations of an entity, and
authorDouglas Gregor <dgregor@apple.com>
Fri, 9 Sep 2011 19:05:14 +0000 (19:05 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 9 Sep 2011 19:05:14 +0000 (19:05 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplate.cpp
test/Modules/module-private.cpp

index 568e0a3b6bafd7b89bef6efb3afa3f9ffe1c3d0c..846b32ba89eb19c9127bb21f5d36cdb42170b0f0 100644 (file)
@@ -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.
 
index 4bdf3802aabd4bdb2228d838a547d9183c1fcbec..3306a0f7f5b7b6f9b1ea22f5a7bd1315e15de9f2 100644 (file)
@@ -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);
 
index 3c692cc57710b485427bd278ea236a2ea2ee3d0a..197e446fd383a7a76f1e0cf6e5cd08f9f06480e9 100644 (file)
@@ -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);
index 63f32d094b9299fb7d69fc7f10e819b05c682042..dbdb184d4a2f522f66d7799e7a9726ab3e4e57dd 100644 (file)
@@ -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());
 
index 4a7be55366a992686491a8c035571a8073563d28..003be8289f626834b4fdc9d4c563f522cb785080 100644 (file)
@@ -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) {
index 9ffb7765af180e8cdad5d8d0c4422d5feeca6672..f8c2905316be0f3ee044ce1eca0c1cab6783ed8a 100644 (file)
@@ -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 {
index eb199aced45dee5613e4b95d6972c8d441aa747b..4b3f6c45d55deedde32eed73a1cce2dc2b7b9af6 100644 (file)
@@ -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());
index 689abd746ad48e56b2832dc6b07aa6d2d2e967a9..3ee59c8a9c1745032de0ca00a4586678d38fca14 100644 (file)
@@ -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