Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/MultilibBuilder.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- MultilibBuilder.cpp - MultilibBuilder Implementation -===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "clang/Driver/MultilibBuilder.h"
10
#include "ToolChains/CommonArgs.h"
11
#include "llvm/ADT/SmallString.h"
12
#include "llvm/ADT/StringMap.h"
13
#include "llvm/Support/Path.h"
14
#include "llvm/Support/Regex.h"
15
#include "llvm/Support/raw_ostream.h"
16
17
using namespace clang;
18
using namespace driver;
19
20
/// normalize Segment to "/foo/bar" or "".
21
38.8k
static void normalizePathSegment(std::string &Segment) {
22
38.8k
  StringRef seg = Segment;
23
24
  // Prune trailing "/" or "./"
25
50.1k
  while (true) {
26
50.1k
    StringRef last = llvm::sys::path::filename(seg);
27
50.1k
    if (last != ".")
28
38.8k
      break;
29
11.3k
    seg = llvm::sys::path::parent_path(seg);
30
11.3k
  }
31
32
38.8k
  if (seg.empty() || 
seg == "/"31.6k
) {
33
7.66k
    Segment.clear();
34
7.66k
    return;
35
7.66k
  }
36
37
  // Add leading '/'
38
31.1k
  if (seg.front() != '/') {
39
1.32k
    Segment = "/" + seg.str();
40
29.8k
  } else {
41
29.8k
    Segment = std::string(seg);
42
29.8k
  }
43
31.1k
}
44
45
MultilibBuilder::MultilibBuilder(StringRef GCC, StringRef OS, StringRef Include)
46
12.0k
    : GCCSuffix(GCC), OSSuffix(OS), IncludeSuffix(Include) {
47
12.0k
  normalizePathSegment(GCCSuffix);
48
12.0k
  normalizePathSegment(OSSuffix);
49
12.0k
  normalizePathSegment(IncludeSuffix);
50
12.0k
}
51
52
MultilibBuilder::MultilibBuilder(StringRef Suffix)
53
3.67k
    : MultilibBuilder(Suffix, Suffix, Suffix) {}
Unexecuted instantiation: clang::driver::MultilibBuilder::MultilibBuilder(llvm::StringRef)
clang::driver::MultilibBuilder::MultilibBuilder(llvm::StringRef)
Line
Count
Source
53
3.67k
    : MultilibBuilder(Suffix, Suffix, Suffix) {}
54
55
1.33k
MultilibBuilder &MultilibBuilder::gccSuffix(StringRef S) {
56
1.33k
  GCCSuffix = std::string(S);
57
1.33k
  normalizePathSegment(GCCSuffix);
58
1.33k
  return *this;
59
1.33k
}
60
61
48
MultilibBuilder &MultilibBuilder::osSuffix(StringRef S) {
62
48
  OSSuffix = std::string(S);
63
48
  normalizePathSegment(OSSuffix);
64
48
  return *this;
65
48
}
66
67
1.32k
MultilibBuilder &MultilibBuilder::includeSuffix(StringRef S) {
68
1.32k
  IncludeSuffix = std::string(S);
69
1.32k
  normalizePathSegment(IncludeSuffix);
70
1.32k
  return *this;
71
1.32k
}
72
73
7.94k
bool MultilibBuilder::isValid() const {
74
7.94k
  llvm::StringMap<int> FlagSet;
75
75.9k
  for (unsigned I = 0, N = Flags.size(); I != N; 
++I67.9k
) {
76
68.3k
    StringRef Flag(Flags[I]);
77
68.3k
    llvm::StringMap<int>::iterator SI = FlagSet.find(Flag.substr(1));
78
79
68.3k
    assert(StringRef(Flag).front() == '-' || StringRef(Flag).front() == '!');
80
81
68.3k
    if (SI == FlagSet.end())
82
66.9k
      FlagSet[Flag.substr(1)] = I;
83
1.41k
    else if (Flags[I] != Flags[SI->getValue()])
84
417
      return false;
85
68.3k
  }
86
7.52k
  return true;
87
7.94k
}
88
89
9.65k
MultilibBuilder &MultilibBuilder::flag(StringRef Flag, bool Disallow) {
90
9.65k
  tools::addMultilibFlag(!Disallow, Flag, Flags);
91
9.65k
  return *this;
92
9.65k
}
93
94
6.66k
Multilib MultilibBuilder::makeMultilib() const {
95
6.66k
  return Multilib(GCCSuffix, OSSuffix, IncludeSuffix, Flags);
96
6.66k
}
97
98
118
MultilibSetBuilder &MultilibSetBuilder::Maybe(const MultilibBuilder &M) {
99
118
  MultilibBuilder Opposite;
100
  // Negate positive flags
101
168
  for (StringRef Flag : M.flags()) {
102
168
    if (Flag.front() == '-')
103
112
      Opposite.flag(Flag, /*Disallow=*/true);
104
168
  }
105
118
  return Either(M, Opposite);
106
118
}
107
108
MultilibSetBuilder &MultilibSetBuilder::Either(const MultilibBuilder &M1,
109
214
                                               const MultilibBuilder &M2) {
110
214
  return Either({M1, M2});
111
214
}
112
113
MultilibSetBuilder &MultilibSetBuilder::Either(const MultilibBuilder &M1,
114
                                               const MultilibBuilder &M2,
115
54
                                               const MultilibBuilder &M3) {
116
54
  return Either({M1, M2, M3});
117
54
}
118
119
MultilibSetBuilder &MultilibSetBuilder::Either(const MultilibBuilder &M1,
120
                                               const MultilibBuilder &M2,
121
                                               const MultilibBuilder &M3,
122
18
                                               const MultilibBuilder &M4) {
123
18
  return Either({M1, M2, M3, M4});
124
18
}
125
126
MultilibSetBuilder &MultilibSetBuilder::Either(const MultilibBuilder &M1,
127
                                               const MultilibBuilder &M2,
128
                                               const MultilibBuilder &M3,
129
                                               const MultilibBuilder &M4,
130
176
                                               const MultilibBuilder &M5) {
131
176
  return Either({M1, M2, M3, M4, M5});
132
176
}
133
134
static MultilibBuilder compose(const MultilibBuilder &Base,
135
7.93k
                               const MultilibBuilder &New) {
136
7.93k
  SmallString<128> GCCSuffix;
137
7.93k
  llvm::sys::path::append(GCCSuffix, "/", Base.gccSuffix(), New.gccSuffix());
138
7.93k
  SmallString<128> OSSuffix;
139
7.93k
  llvm::sys::path::append(OSSuffix, "/", Base.osSuffix(), New.osSuffix());
140
7.93k
  SmallString<128> IncludeSuffix;
141
7.93k
  llvm::sys::path::append(IncludeSuffix, "/", Base.includeSuffix(),
142
7.93k
                          New.includeSuffix());
143
144
7.93k
  MultilibBuilder Composed(GCCSuffix, OSSuffix, IncludeSuffix);
145
146
7.93k
  MultilibBuilder::flags_list &Flags = Composed.flags();
147
148
7.93k
  Flags.insert(Flags.end(), Base.flags().begin(), Base.flags().end());
149
7.93k
  Flags.insert(Flags.end(), New.flags().begin(), New.flags().end());
150
151
7.93k
  return Composed;
152
7.93k
}
153
154
MultilibSetBuilder &
155
522
MultilibSetBuilder::Either(ArrayRef<MultilibBuilder> MultilibSegments) {
156
522
  multilib_list Composed;
157
158
522
  if (Multilibs.empty())
159
352
    Multilibs.insert(Multilibs.end(), MultilibSegments.begin(),
160
352
                     MultilibSegments.end());
161
170
  else {
162
386
    for (const auto &New : MultilibSegments) {
163
7.93k
      for (const auto &Base : Multilibs) {
164
7.93k
        MultilibBuilder MO = compose(Base, New);
165
7.93k
        if (MO.isValid())
166
7.52k
          Composed.push_back(MO);
167
7.93k
      }
168
386
    }
169
170
170
    Multilibs = Composed;
171
170
  }
172
173
522
  return *this;
174
522
}
175
176
177
MultilibSetBuilder &MultilibSetBuilder::FilterOut(const char *Regex) {
177
177
  llvm::Regex R(Regex);
178
177
#ifndef NDEBUG
179
177
  std::string Error;
180
177
  if (!R.isValid(Error)) {
181
0
    llvm::errs() << Error;
182
0
    llvm_unreachable("Invalid regex!");
183
0
  }
184
177
#endif
185
6.55k
  llvm::erase_if(Multilibs, [&R](const MultilibBuilder &M) {
186
6.55k
    return R.match(M.gccSuffix());
187
6.55k
  });
188
177
  return *this;
189
177
}
190
191
354
MultilibSet MultilibSetBuilder::makeMultilibSet() const {
192
354
  MultilibSet Result;
193
4.61k
  for (const auto &M : Multilibs) {
194
4.61k
    Result.push_back(M.makeMultilib());
195
4.61k
  }
196
354
  return Result;
197
354
}