r239750 - [modules] Better support for redefinitions of an entity from the same module.

Richard Smith richard-llvm at metafoo.co.uk
Mon Jun 15 13:15:48 PDT 2015


Author: rsmith
Date: Mon Jun 15 15:15:48 2015
New Revision: 239750

URL: http://llvm.org/viewvc/llvm-project?rev=239750&view=rev
Log:
[modules] Better support for redefinitions of an entity from the same module.

Support this across module save/reload and extend the 'missing import'
diagnostics with a list of providing modules.

Added:
    cfe/trunk/test/Modules/Inputs/submodules-merge-defs/use-defs-2.h
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h
    cfe/trunk/test/Modules/Inputs/submodules-merge-defs/module.modulemap
    cfe/trunk/test/Modules/module-private.cpp
    cfe/trunk/test/Modules/submodules-merge-defs.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=239750&r1=239749&r2=239750&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jun 15 15:15:48 2015
@@ -7637,9 +7637,11 @@ def err_module_private_local_class : Err
   "local %select{struct|interface|union|class|enum}0 cannot be declared "
   "__module_private__">;
 def err_module_private_declaration : Error<
-  "declaration of %0 must be imported from module '%1' before it is required">;
-def err_module_private_definition : Error<
-  "definition of %0 must be imported from module '%1' before it is required">;
+  "%select{declaration|definition}0 of %1 must be imported from "
+  "module '%2' before it is required">;
+def err_module_private_declaration_multiple : Error<
+  "%select{declaration|definition}0 of %1 must be imported from "
+  "one of the following modules before it is required:%2">;
 def err_module_import_in_extern_c : Error<
   "import of C++ module '%0' appears within extern \"C\" language linkage "
   "specification">;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=239750&r1=239749&r2=239750&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Jun 15 15:15:48 2015
@@ -1730,6 +1730,11 @@ public:
   void createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
                                                   Module *Mod);
 
+  /// \brief Diagnose that the specified declaration needs to be visible but
+  /// isn't, and suggest a module import that would resolve the problem.
+  void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
+                             bool NeedDefinition, bool Recover = true);
+
   /// \brief Retrieve a suitable printing policy.
   PrintingPolicy getPrintingPolicy() const {
     return getPrintingPolicy(Context, PP);

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=239750&r1=239749&r2=239750&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Mon Jun 15 15:15:48 2015
@@ -4661,6 +4661,50 @@ static NamedDecl *getDefinitionToImport(
   return nullptr;
 }
 
+void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
+                                 bool NeedDefinition, bool Recover) {
+  assert(!isVisible(Decl) && "missing import for non-hidden decl?");
+
+  // Suggest importing a module providing the definition of this entity, if
+  // possible.
+  NamedDecl *Def = getDefinitionToImport(Decl);
+  if (!Def)
+    Def = Decl;
+
+  // FIXME: Add a Fix-It that imports the corresponding module or includes
+  // the header.
+  Module *Owner = getOwningModule(Decl);
+  assert(Owner && "definition of hidden declaration is not in a module");
+
+  auto Merged = Context.getModulesWithMergedDefinition(Decl);
+  if (!Merged.empty()) {
+    std::string ModuleList;
+    ModuleList += "\n        ";
+    ModuleList += Owner->getFullModuleName();
+    unsigned N = 0;
+    for (Module *M : Merged) {
+      ModuleList += "\n        ";
+      if (++N == 5 && Merged.size() != N) {
+        ModuleList += "[...]";
+        break;
+      }
+      ModuleList += M->getFullModuleName();
+    }
+
+    Diag(Loc, diag::err_module_private_declaration_multiple)
+      << NeedDefinition << Decl << ModuleList;
+  } else {
+    Diag(Loc, diag::err_module_private_declaration)
+      << NeedDefinition << Decl << Owner->getFullModuleName();
+  }
+  Diag(Decl->getLocation(), NeedDefinition ? diag::note_previous_definition
+                                           : diag::note_previous_declaration);
+
+  // Try to recover by implicitly importing this module.
+  if (Recover)
+    createImplicitModuleImportForErrorRecovery(Loc, Owner);
+}
+
 /// \brief Diagnose a successfully-corrected typo. Separated from the correction
 /// itself to allow external validation of the result, etc.
 ///
@@ -4687,23 +4731,8 @@ void Sema::diagnoseTypo(const TypoCorrec
     NamedDecl *Decl = Correction.getCorrectionDecl();
     assert(Decl && "import required but no declaration to import");
 
-    // Suggest importing a module providing the definition of this entity, if
-    // possible.
-    NamedDecl *Def = getDefinitionToImport(Decl);
-    if (!Def)
-      Def = Decl;
-    Module *Owner = getOwningModule(Def);
-    assert(Owner && "definition of hidden declaration is not in a module");
-
-    Diag(Correction.getCorrectionRange().getBegin(),
-         diag::err_module_private_declaration)
-      << Def << Owner->getFullModuleName();
-    Diag(Def->getLocation(), diag::note_previous_declaration);
-
-    // Recover by implicitly importing this module.
-    if (ErrorRecovery)
-      createImplicitModuleImportForErrorRecovery(
-          Correction.getCorrectionRange().getBegin(), Owner);
+    diagnoseMissingImport(Correction.getCorrectionRange().getBegin(), Decl,
+                          /*NeedDefinition*/ false, ErrorRecovery);
     return;
   }
 

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=239750&r1=239749&r2=239750&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon Jun 15 15:15:48 2015
@@ -5239,20 +5239,8 @@ bool Sema::RequireCompleteTypeImpl(Sourc
     // If we know about the definition but it is not visible, complain.
     NamedDecl *SuggestedDef = nullptr;
     if (!Diagnoser.Suppressed && Def &&
-        !hasVisibleDefinition(Def, &SuggestedDef)) {
-      // Suppress this error outside of a SFINAE context if we've already
-      // emitted the error once for this type. There's no usefulness in
-      // repeating the diagnostic.
-      // FIXME: Add a Fix-It that imports the corresponding module or includes
-      // the header.
-      Module *Owner = getOwningModule(SuggestedDef);
-      Diag(Loc, diag::err_module_private_definition)
-        << T << Owner->getFullModuleName();
-      Diag(SuggestedDef->getLocation(), diag::note_previous_definition);
-
-      // Try to recover by implicitly importing this module.
-      createImplicitModuleImportForErrorRecovery(Loc, Owner);
-    }
+        !hasVisibleDefinition(Def, &SuggestedDef))
+      diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true);
 
     // We lock in the inheritance model once somebody has asked us to ensure
     // that a pointer-to-member type is complete.

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=239750&r1=239749&r2=239750&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Jun 15 15:15:48 2015
@@ -5764,8 +5764,5 @@ void ASTWriter::DeclarationMarkedOpenMPT
 void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {
   assert(!WritingAST && "Already writing the AST!");
   assert(D->isHidden() && "expected a hidden declaration");
-  if (!D->isFromASTFile())
-    return;
-
   DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_EXPORTED, M));
 }

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=239750&r1=239749&r2=239750&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h (original)
+++ cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h Mon Jun 15 15:15:48 2015
@@ -31,7 +31,7 @@ template<typename T> struct F {
 template<typename T> int F<T>::f() { return 0; }
 template<typename T> template<typename U> int F<T>::g() { return 0; }
 template<typename T> int F<T>::n = 0;
-template<> template<typename U> int F<char>::g() { return 0; }
+//template<> template<typename U> int F<char>::g() { return 0; } // FIXME: Re-enable this once we support merging member specializations.
 template<> struct F<void> { int h(); };
 inline int F<void>::h() { return 0; }
 template<typename T> struct F<T *> { int i(); };

Modified: cfe/trunk/test/Modules/Inputs/submodules-merge-defs/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/submodules-merge-defs/module.modulemap?rev=239750&r1=239749&r2=239750&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/submodules-merge-defs/module.modulemap (original)
+++ cfe/trunk/test/Modules/Inputs/submodules-merge-defs/module.modulemap Mon Jun 15 15:15:48 2015
@@ -2,6 +2,7 @@ module "stuff" {
   textual header "defs.h"
   module "empty" { header "empty.h" }
   module "use" { header "use-defs.h" }
+  module "use-2" { requires use_defs_twice header "use-defs-2.h" }
 }
 
 module "redef" {

Added: cfe/trunk/test/Modules/Inputs/submodules-merge-defs/use-defs-2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/submodules-merge-defs/use-defs-2.h?rev=239750&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/submodules-merge-defs/use-defs-2.h (added)
+++ cfe/trunk/test/Modules/Inputs/submodules-merge-defs/use-defs-2.h Mon Jun 15 15:15:48 2015
@@ -0,0 +1 @@
+#include "defs.h"

Modified: cfe/trunk/test/Modules/module-private.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/module-private.cpp?rev=239750&r1=239749&r2=239750&view=diff
==============================================================================
--- cfe/trunk/test/Modules/module-private.cpp (original)
+++ cfe/trunk/test/Modules/module-private.cpp Mon Jun 15 15:15:48 2015
@@ -14,7 +14,7 @@ void test() {
 int test_broken() {
   HiddenStruct hidden; // \
   // expected-error{{must use 'struct' tag to refer to type 'HiddenStruct' in this scope}} \
-  // expected-error{{definition of 'struct HiddenStruct' must be imported}}
+  // expected-error{{definition of 'HiddenStruct' must be imported}}
   // expected-note at Inputs/module_private_left.h:3 {{previous definition is here}}
 
   Integer i; // expected-error{{unknown type name 'Integer'}}

Modified: cfe/trunk/test/Modules/submodules-merge-defs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/submodules-merge-defs.cpp?rev=239750&r1=239749&r2=239750&view=diff
==============================================================================
--- cfe/trunk/test/Modules/submodules-merge-defs.cpp (original)
+++ cfe/trunk/test/Modules/submodules-merge-defs.cpp Mon Jun 15 15:15:48 2015
@@ -4,6 +4,7 @@
 // RUN: %clang_cc1 -x c++ -std=c++11 -fmodules-cache-path=%t -fmodules -I %S/Inputs/submodules-merge-defs %s -verify -fno-modules-error-recovery -fmodules-local-submodule-visibility -DTEXTUAL
 // RUN: %clang_cc1 -x c++ -std=c++11 -fmodules-cache-path=%t -fmodules -I %S/Inputs/submodules-merge-defs %s -verify -fno-modules-error-recovery -fmodules-local-submodule-visibility
 // RUN: %clang_cc1 -x c++ -std=c++11 -fmodules-cache-path=%t -fmodule-maps -I %S/Inputs/submodules-merge-defs %s -verify -fno-modules-error-recovery -fmodules-local-submodule-visibility -DTEXTUAL -DEARLY_INDIRECT_INCLUDE
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules-cache-path=%t -fmodules -I %S/Inputs/submodules-merge-defs %s -verify -fno-modules-error-recovery -fmodules-local-submodule-visibility -fmodule-feature use_defs_twice -DIMPORT_USE_2
 
 // Trigger import of definitions, but don't make them visible.
 #include "empty.h"
@@ -11,7 +12,14 @@
 #include "indirect.h"
 #endif
 
-A pre_a; // expected-error {{must be imported}} expected-error {{must use 'struct'}}
+A pre_a; // expected-error {{must use 'struct'}}
+#ifdef IMPORT_USE_2
+// expected-error-re at -2 {{must be imported from one of {{.*}}stuff.use{{.*}}stuff.use-2}}
+#elif EARLY_INDIRECT_INCLUDE
+// expected-error at -4 {{must be imported from module 'merged-defs'}}
+#else
+// expected-error at -6 {{must be imported from module 'stuff.use'}}
+#endif
 // expected-note at defs.h:1 +{{here}}
 // expected-note at defs.h:2 +{{here}}
 int pre_use_a = use_a(pre_a); // expected-error {{'A' must be imported}} expected-error {{'use_a' must be imported}}
@@ -46,6 +54,8 @@ J<> pre_j; // expected-error {{must be i
 // Make definitions from second module visible.
 #ifdef TEXTUAL
 #include "import-and-redefine.h"
+#elif defined IMPORT_USE_2
+#include "use-defs-2.h"
 #else
 #include "merged-defs.h"
 #endif
@@ -61,13 +71,6 @@ int post_use_dx = use_dx(post_dx);
 int post_e = E(0);
 int post_ff = F<char>().f();
 int post_fg = F<char>().g<int>();
-#ifdef EARLY_INDIRECT_INCLUDE
-// FIXME: Properly track the owning module for a member specialization.
-// expected-error at defs.h:34 {{redefinition}}
-// expected-note at defs.h:34 {{previous definition}}
-// expected-error at -5 {{no matching member function}}
-// expected-note at defs.h:34 {{substitution failure}}
-#endif
 J<> post_j;
 template<typename T, int N, template<typename> class K> struct J;
 J<> post_j2;





More information about the cfe-commits mailing list