Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmIncludeGuardCommand.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmIncludeGuardCommand.h"
4
5
#include "cmCryptoHash.h"
6
#include "cmExecutionStatus.h"
7
#include "cmMakefile.h"
8
#include "cmStateDirectory.h"
9
#include "cmStateSnapshot.h"
10
#include "cmStringAlgorithms.h"
11
#include "cmValue.h"
12
#include "cmake.h"
13
14
namespace {
15
16
enum IncludeGuardScope
17
{
18
  VARIABLE,
19
  DIRECTORY,
20
  GLOBAL
21
};
22
23
std::string GetIncludeGuardVariableName(std::string const& filePath)
24
0
{
25
0
  cmCryptoHash hasher(cmCryptoHash::AlgoMD5);
26
0
  return cmStrCat("__INCGUARD_", hasher.HashString(filePath), "__");
27
0
}
28
29
bool CheckIncludeGuardIsSet(cmMakefile* mf, std::string const& includeGuardVar)
30
0
{
31
0
  if (mf->GetProperty(includeGuardVar)) {
32
0
    return true;
33
0
  }
34
0
  cmStateSnapshot dirSnapshot =
35
0
    mf->GetStateSnapshot().GetBuildsystemDirectoryParent();
36
0
  while (dirSnapshot.GetState()) {
37
0
    cmStateDirectory stateDir = dirSnapshot.GetDirectory();
38
0
    if (stateDir.GetProperty(includeGuardVar)) {
39
0
      return true;
40
0
    }
41
0
    dirSnapshot = dirSnapshot.GetBuildsystemDirectoryParent();
42
0
  }
43
0
  return false;
44
0
}
45
46
} // anonymous namespace
47
48
// cmIncludeGuardCommand
49
bool cmIncludeGuardCommand(std::vector<std::string> const& args,
50
                           cmExecutionStatus& status)
51
0
{
52
0
  if (args.size() > 1) {
53
0
    status.SetError(
54
0
      "given an invalid number of arguments. The command takes at "
55
0
      "most 1 argument.");
56
0
    return false;
57
0
  }
58
59
0
  IncludeGuardScope scope = VARIABLE;
60
61
0
  if (!args.empty()) {
62
0
    std::string const& arg = args[0];
63
0
    if (arg == "DIRECTORY") {
64
0
      scope = DIRECTORY;
65
0
    } else if (arg == "GLOBAL") {
66
0
      scope = GLOBAL;
67
0
    } else {
68
0
      status.SetError("given an invalid scope: " + arg);
69
0
      return false;
70
0
    }
71
0
  }
72
73
0
  std::string includeGuardVar = GetIncludeGuardVariableName(
74
0
    *status.GetMakefile().GetDefinition("CMAKE_CURRENT_LIST_FILE"));
75
76
0
  cmMakefile* const mf = &status.GetMakefile();
77
78
0
  switch (scope) {
79
0
    case VARIABLE:
80
0
      if (mf->IsDefinitionSet(includeGuardVar)) {
81
0
        status.SetReturnInvoked();
82
0
        return true;
83
0
      }
84
0
      mf->AddDefinitionBool(includeGuardVar, true);
85
0
      break;
86
0
    case DIRECTORY:
87
0
      if (CheckIncludeGuardIsSet(mf, includeGuardVar)) {
88
0
        status.SetReturnInvoked();
89
0
        return true;
90
0
      }
91
0
      mf->SetProperty(includeGuardVar, "TRUE");
92
0
      break;
93
0
    case GLOBAL:
94
0
      cmake* const cm = mf->GetCMakeInstance();
95
0
      if (cm->GetProperty(includeGuardVar)) {
96
0
        status.SetReturnInvoked();
97
0
        return true;
98
0
      }
99
0
      cm->SetProperty(includeGuardVar, "TRUE");
100
0
      break;
101
0
  }
102
103
0
  return true;
104
0
}