Преглед изворни кода

Provide and use CM_FALLTHROUGH

Daniel Pfeifer пре 8 година
родитељ
комит
8d7b3ef5d4

+ 11 - 0
Source/Checks/cm_cxx_attribute_fallthrough.cxx

@@ -0,0 +1,11 @@
+int main(int argc, char* argv[])
+{
+  int i = 3;
+  switch (argc) {
+    case 1:
+      i = 0;
+      __attribute__((fallthrough));
+    default:
+      return i;
+  }
+}

+ 11 - 0
Source/Checks/cm_cxx_fallthrough.cxx

@@ -0,0 +1,11 @@
+int main(int argc, char* argv[])
+{
+  int i = 3;
+  switch (argc) {
+    case 1:
+      i = 0;
+      [[fallthrough]];
+    default:
+      return i;
+  }
+}

+ 7 - 0
Source/Checks/cm_cxx_features.cmake

@@ -38,6 +38,13 @@ endfunction()
 
 cm_check_cxx_feature(auto_ptr)
 cm_check_cxx_feature(eq_delete)
+cm_check_cxx_feature(fallthrough)
+if(NOT CMake_HAVE_CXX_FALLTHROUGH)
+  cm_check_cxx_feature(gnu_fallthrough)
+  if(NOT CMake_HAVE_CXX_GNU_FALLTHROUGH)
+    cm_check_cxx_feature(attribute_fallthrough)
+  endif()
+endif()
 cm_check_cxx_feature(make_unique)
 if(CMake_HAVE_CXX_MAKE_UNIQUE)
   set(CMake_HAVE_CXX_UNIQUE_PTR 1)

+ 11 - 0
Source/Checks/cm_cxx_gnu_fallthrough.cxx

@@ -0,0 +1,11 @@
+int main(int argc, char* argv[])
+{
+  int i = 3;
+  switch (argc) {
+    case 1:
+      i = 0;
+      [[gnu::fallthrough]];
+    default:
+      return i;
+  }
+}

+ 2 - 2
Source/cmConditionEvaluator.cxx

@@ -285,12 +285,12 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
   bool oldResult = this->GetBooleanValueOld(newArg, oneArg);
   if (newResult != oldResult) {
     switch (this->Policy12Status) {
-      case cmPolicies::WARN: {
+      case cmPolicies::WARN:
         errorString = "An argument named \"" + newArg.GetValue() +
           "\" appears in a conditional statement.  " +
           cmPolicies::GetPolicyWarning(cmPolicies::CMP0012);
         status = cmake::AUTHOR_WARNING;
-      }
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         return oldResult;
       case cmPolicies::REQUIRED_IF_USED:

+ 13 - 0
Source/cmConfigure.cmake.h.in

@@ -22,6 +22,9 @@
 #cmakedefine CMAKE_USE_LIBUV
 #cmakedefine CMake_HAVE_CXX_AUTO_PTR
 #cmakedefine CMake_HAVE_CXX_EQ_DELETE
+#cmakedefine CMake_HAVE_CXX_FALLTHROUGH
+#cmakedefine CMake_HAVE_CXX_GNU_FALLTHROUGH
+#cmakedefine CMake_HAVE_CXX_ATTRIBUTE_FALLTHROUGH
 #cmakedefine CMake_HAVE_CXX_MAKE_UNIQUE
 #cmakedefine CMake_HAVE_CXX_NULLPTR
 #cmakedefine CMake_HAVE_CXX_OVERRIDE
@@ -37,6 +40,16 @@
 #define CM_EQ_DELETE
 #endif
 
+#if defined(CMake_HAVE_CXX_FALLTHROUGH)
+#define CM_FALLTHROUGH [[fallthrough]]
+#elif defined(CMake_HAVE_CXX_GNU_FALLTHROUGH)
+#define CM_FALLTHROUGH [[gnu::fallthrough]]
+elif defined(CMake_HAVE_CXX_ATTRIBUTE_FALLTHROUGH)
+#define CM_FALLTHROUGH __attribute__((fallthrough))
+#else
+#define CM_FALLTHROUGH
+#endif
+
 #ifdef CMake_HAVE_CXX_NULLPTR
 #define CM_NULLPTR nullptr
 #else

+ 4 - 0
Source/cmCoreTryCompile.cxx

@@ -219,6 +219,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
             if (tgt->IsExecutableWithExports()) {
               break;
             }
+            CM_FALLTHROUGH;
           default:
             this->Makefile->IssueMessage(
               cmake::FATAL_ERROR,
@@ -516,6 +517,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
         this->Makefile->IssueMessage(
           cmake::FATAL_ERROR,
           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0066));
+        CM_FALLTHROUGH;
       case cmPolicies::NEW: {
         // NEW behavior is to pass config-specific compiler flags.
         static std::string const cfgDefault = "DEBUG";
@@ -553,6 +555,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
         this->Makefile->IssueMessage(
           cmake::FATAL_ERROR,
           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0056));
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior is to pass linker flags.
         {
@@ -693,6 +696,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
         case cmPolicies::WARN:
           warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
             "CMAKE_POLICY_WARNING_CMP0067");
+          CM_FALLTHROUGH;
         case cmPolicies::OLD:
           // OLD behavior is to not honor the language standard variables.
           honorStandard = false;

+ 1 - 0
Source/cmExportFileGenerator.cxx

@@ -273,6 +273,7 @@ static bool checkInterfaceDirs(const std::string& prepro,
                 << std::endl;
               target->GetLocalGenerator()->IssueMessage(cmake::AUTHOR_WARNING,
                                                         s.str());
+              CM_FALLTHROUGH;
             }
             case cmPolicies::OLD:
               shouldContinue = true;

+ 1 - 0
Source/cmExtraCodeLiteGenerator.cxx

@@ -141,6 +141,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget(
         case cmStateEnums::STATIC_LIBRARY:
         case cmStateEnums::MODULE_LIBRARY:
           visualname = "lib" + visualname;
+          CM_FALLTHROUGH;
         case cmStateEnums::EXECUTABLE:
           xml->StartElement("Project");
           xml->Attribute("Name", visualname);

+ 1 - 0
Source/cmFileCommand.cxx

@@ -1770,6 +1770,7 @@ protected:
         if (this->Makefile->IsOn("CMAKE_INSTALL_SO_NO_EXE")) {
           break;
         }
+        CM_FALLTHROUGH;
       case cmInstallType_EXECUTABLE:
       case cmInstallType_PROGRAMS:
         this->FilePermissions |= mode_owner_execute;

+ 16 - 8
Source/cmFindPackageCommand.cxx

@@ -423,13 +423,17 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
              &parsed_minor, &parsed_patch, &parsed_tweak);
     switch (this->VersionCount) {
       case 4:
-        this->VersionTweak = parsed_tweak; // no break!
+        this->VersionTweak = parsed_tweak;
+        CM_FALLTHROUGH;
       case 3:
-        this->VersionPatch = parsed_patch; // no break!
+        this->VersionPatch = parsed_patch;
+        CM_FALLTHROUGH;
       case 2:
-        this->VersionMinor = parsed_minor; // no break!
+        this->VersionMinor = parsed_minor;
+        CM_FALLTHROUGH;
       case 1:
-        this->VersionMajor = parsed_major; // no break!
+        this->VersionMajor = parsed_major;
+        CM_FALLTHROUGH;
       default:
         break;
     }
@@ -1542,13 +1546,17 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
                &parsed_minor, &parsed_patch, &parsed_tweak);
       switch (this->VersionFoundCount) {
         case 4:
-          this->VersionFoundTweak = parsed_tweak; // no break!
+          this->VersionFoundTweak = parsed_tweak;
+          CM_FALLTHROUGH;
         case 3:
-          this->VersionFoundPatch = parsed_patch; // no break!
+          this->VersionFoundPatch = parsed_patch;
+          CM_FALLTHROUGH;
         case 2:
-          this->VersionFoundMinor = parsed_minor; // no break!
+          this->VersionFoundMinor = parsed_minor;
+          CM_FALLTHROUGH;
         case 1:
-          this->VersionFoundMajor = parsed_major; // no break!
+          this->VersionFoundMajor = parsed_major;
+          CM_FALLTHROUGH;
         default:
           break;
       }

+ 2 - 0
Source/cmGeneratorExpressionNode.cxx

@@ -410,6 +410,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode
           e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044);
           context->LG->GetCMakeInstance()->IssueMessage(
             cmake::AUTHOR_WARNING, e.str(), context->Backtrace);
+          CM_FALLTHROUGH;
         }
         case cmPolicies::OLD:
           return "1";
@@ -1459,6 +1460,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode
             lg->IssueMessage(
               cmake::AUTHOR_WARNING,
               cmPolicies::GetPolicyWarning(policyForString(policy)));
+            CM_FALLTHROUGH;
           case cmPolicies::REQUIRED_IF_USED:
           case cmPolicies::REQUIRED_ALWAYS:
           case cmPolicies::OLD:

+ 8 - 3
Source/cmGeneratorTarget.cxx

@@ -2481,6 +2481,7 @@ static void processIncludeDirectories(
           switch (tgt->GetPolicyStatusCMP0027()) {
             case cmPolicies::WARN:
               e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n";
+              CM_FALLTHROUGH;
             case cmPolicies::OLD:
               messageType = cmake::AUTHOR_WARNING;
               break;
@@ -2837,6 +2838,7 @@ void cmGeneratorTarget::GetCompileDefinitions(
           std::ostringstream e;
           e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043);
           this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+          CM_FALLTHROUGH;
         }
         case cmPolicies::OLD: {
           cmGeneratorExpression ge;
@@ -4132,11 +4134,14 @@ void cmGeneratorTarget::GetTargetVersion(bool soversion, int& major,
     switch (sscanf(version, "%d.%d.%d", &parsed_major, &parsed_minor,
                    &parsed_patch)) {
       case 3:
-        patch = parsed_patch; // no break!
+        patch = parsed_patch;
+        CM_FALLTHROUGH;
       case 2:
-        minor = parsed_minor; // no break!
+        minor = parsed_minor;
+        CM_FALLTHROUGH;
       case 1:
-        major = parsed_major; // no break!
+        major = parsed_major;
+        CM_FALLTHROUGH;
       default:
         break;
     }

+ 1 - 0
Source/cmGetDirectoryPropertyCommand.cxx

@@ -78,6 +78,7 @@ bool cmGetDirectoryPropertyCommand::InitialPass(
           this->Makefile->IssueMessage(
             cmake::AUTHOR_WARNING,
             cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
+          CM_FALLTHROUGH;
         case cmPolicies::OLD:
           this->StoreResult(variable, this->Makefile->GetDefineFlagsCMP0059());
           return true;

+ 1 - 0
Source/cmGetPropertyCommand.cxx

@@ -232,6 +232,7 @@ bool cmGetPropertyCommand::HandleDirectoryMode()
       case cmPolicies::WARN:
         mf->IssueMessage(cmake::AUTHOR_WARNING,
                          cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         return this->StoreResult(mf->GetDefineFlagsCMP0059());
       case cmPolicies::NEW:

+ 3 - 0
Source/cmGlobalGenerator.cxx

@@ -838,6 +838,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
           /* clang-format on */
           mf->IssueMessage(cmake::AUTHOR_WARNING, w.str());
         }
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         // OLD behavior is to convert AppleClang to Clang.
         mf->AddDefinition(compilerIdVar, "Clang");
@@ -867,6 +868,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
           /* clang-format on */
           mf->IssueMessage(cmake::AUTHOR_WARNING, w.str());
         }
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         // OLD behavior is to convert QCC to GNU.
         mf->AddDefinition(compilerIdVar, "GNU");
@@ -881,6 +883,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
         mf->IssueMessage(
           cmake::FATAL_ERROR,
           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0047));
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior is to keep QCC.
         break;

+ 2 - 2
Source/cmInstallCommand.cxx

@@ -1406,11 +1406,11 @@ bool cmInstallCommand::MakeFilesFullPath(
 bool cmInstallCommand::CheckCMP0006(bool& failure)
 {
   switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) {
-    case cmPolicies::WARN: {
+    case cmPolicies::WARN:
       this->Makefile->IssueMessage(
         cmake::AUTHOR_WARNING,
         cmPolicies::GetPolicyWarning(cmPolicies::CMP0006));
-    }
+      CM_FALLTHROUGH;
     case cmPolicies::OLD:
       // OLD behavior is to allow compatibility
       return true;

+ 1 - 0
Source/cmLinkDirectoriesCommand.cxx

@@ -49,6 +49,7 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
       case cmPolicies::REQUIRED_ALWAYS:
         e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0015);
         this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior converts
         convertToAbsolute = true;

+ 4 - 1
Source/cmLocalGenerator.cxx

@@ -960,6 +960,7 @@ void cmLocalGenerator::GetTargetFlags(
       break;
     case cmStateEnums::MODULE_LIBRARY:
       libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
+      CM_FALLTHROUGH;
     case cmStateEnums::SHARED_LIBRARY: {
       linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable);
       linkFlags += " ";
@@ -1248,6 +1249,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065(
           /* clang-format on */
           this->IssueMessage(cmake::AUTHOR_WARNING, w.str());
         }
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         // OLD behavior is to always add the flags
         add_shlib_flags = true;
@@ -1257,6 +1259,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065(
         this->IssueMessage(
           cmake::FATAL_ERROR,
           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065));
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior is to only add the flags if ENABLE_EXPORTS is on
         add_shlib_flags = tgt.GetPropertyAsBool("ENABLE_EXPORTS");
@@ -1747,7 +1750,7 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared,
             << cmPolicies::GetPolicyWarning(cmPolicies::CMP0018);
 
           this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
-          // fall through to OLD behaviour
+          CM_FALLTHROUGH;
         }
         case cmPolicies::OLD:
           return true;

+ 10 - 1
Source/cmMakefile.cxx

@@ -360,6 +360,7 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf,
         // We should never make this policy required, but we handle it
         // here just in case.
         this->CheckCMP0011 = true;
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior is to push a (strong) scope.
         this->Makefile->PushPolicy();
@@ -1161,6 +1162,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
       case cmPolicies::WARN:
         this->IssueMessage(cmake::AUTHOR_WARNING,
                            cmPolicies::GetPolicyWarning(cmPolicies::CMP0005));
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         // OLD behavior is to not escape the value.  We should not
         // convert the definition to use the property.
@@ -1511,6 +1513,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
       case cmPolicies::REQUIRED_IF_USED:
       case cmPolicies::REQUIRED_ALWAYS:
         e << "\n" << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0014);
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior prints the error.
         this->IssueMessage(cmake::FATAL_ERROR, e.str());
@@ -2340,6 +2343,7 @@ const char* cmMakefile::ExpandVariablesInString(
         newErrorstr, newResult, escapeQuotes, noEscapes, atOnly, filename,
         line, removeEmpty, replaceAt);
       this->SuppressWatches = false;
+      CM_FALLTHROUGH;
     }
     case cmPolicies::OLD:
       mtype =
@@ -2496,6 +2500,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
       switch (this->GetPolicyStatus(cmPolicies::CMP0010)) {
         case cmPolicies::WARN:
           error << "\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0010);
+          CM_FALLTHROUGH;
         case cmPolicies::OLD:
           // OLD behavior is to just warn and continue.
           mtype = cmake::AUTHOR_WARNING;
@@ -2649,6 +2654,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
           }
           break;
         }
+        CM_FALLTHROUGH;
       case '\\':
         if (!noEscapes) {
           const char* next = in + 1;
@@ -3386,7 +3392,7 @@ std::string cmMakefile::GetModulesFile(const char* filename) const
           /* clang-format on */
 
           this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
-          // break;  // fall through to OLD behaviour
+          CM_FALLTHROUGH;
         }
         case cmPolicies::OLD:
           result = moduleInCMakeModulePath;
@@ -3779,6 +3785,7 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg,
       case cmPolicies::WARN:
         this->IssueMessage(cmake::AUTHOR_WARNING,
                            cmPolicies::GetPolicyWarning(cmPolicies::CMP0002));
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         return true;
       case cmPolicies::REQUIRED_IF_USED:
@@ -3864,12 +3871,14 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath,
         << "compatibility.";
       /* clang-format on */
       this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+      CM_FALLTHROUGH;
     case cmPolicies::OLD:
       // OLD behavior does not warn.
       return true;
     case cmPolicies::REQUIRED_IF_USED:
     case cmPolicies::REQUIRED_ALWAYS:
       e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0013) << "\n";
+      CM_FALLTHROUGH;
     case cmPolicies::NEW:
       // NEW behavior prints the error.
       /* clang-format off */

+ 1 - 0
bootstrap

@@ -1307,6 +1307,7 @@ cmake_report cmConfigure.h${_tmp} "#define CMAKE_BIN_DIR \"/bootstrap-not-insall
 cmake_report cmConfigure.h${_tmp} "#define CMAKE_DATA_DIR \"/bootstrap-not-insalled\""
 cmake_report cmConfigure.h${_tmp} "#define CMAKE_BOOTSTRAP"
 cmake_report cmConfigure.h${_tmp} "#define CM_EQ_DELETE"
+cmake_report cmConfigure.h${_tmp} "#define CM_FALLTHROUGH"
 cmake_report cmConfigure.h${_tmp} "#define CM_NULLPTR 0"
 cmake_report cmConfigure.h${_tmp} "#define CM_OVERRIDE"
 cmake_report cmConfigure.h${_tmp} "#define CM_DISABLE_COPY(Class)"