Skip to content

Commit 9401c95

Browse files
committed
[clang][Driver] Improve multilib custom error reporting.
If `multilib.yaml` reports a custom error message for some unsupported configuration, it's not very helpful to display that error message _first_, and then follow it up with a huge list of all the multilib configurations that _are_ supported. In interactive use, the list is likely to scroll the most important message off the top of the user's window, leaving them with just a long list of available libraries, without a visible explanation of _why_ clang just printed that long list. Also, in general, it makes more intuitive sense to print the message last that shows why compilation can't continue, because that's where users are most likely to look for the reason why something stopped.
1 parent 531253a commit 9401c95

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

clang/lib/Driver/Multilib.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
9999
llvm::SmallVectorImpl<Multilib> &Selected) const {
100100
llvm::StringSet<> FlagSet(expandFlags(Flags));
101101
Selected.clear();
102+
bool AnyErrors = false;
102103

103104
// Decide which multilibs we're going to select at all.
104105
llvm::DenseSet<StringRef> ExclusiveGroupsSelected;
@@ -123,12 +124,11 @@ bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
123124
}
124125

125126
// If this multilib is actually a placeholder containing a fatal
126-
// error message written by the multilib.yaml author, display that
127-
// error message, and return failure.
128-
if (M.isError()) {
129-
D.Diag(clang::diag::err_drv_multilib_custom_error) << M.getErrorMessage();
130-
return false;
131-
}
127+
// error message written by the multilib.yaml author, then set a
128+
// flag that will cause a failure return. Our caller will display
129+
// the error message.
130+
if (M.isError())
131+
AnyErrors = true;
132132

133133
// Select this multilib.
134134
Selected.push_back(M);
@@ -138,7 +138,7 @@ bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
138138
// round.
139139
std::reverse(Selected.begin(), Selected.end());
140140

141-
return !Selected.empty();
141+
return !AnyErrors && !Selected.empty();
142142
}
143143

144144
llvm::StringSet<>

clang/lib/Driver/ToolChains/BareMetal.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,27 @@ static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
186186
return;
187187
D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
188188
std::stringstream ss;
189+
190+
// If multilib selection didn't complete successfully, report a list
191+
// of all the configurations the user could have provided.
189192
for (const Multilib &Multilib : Result.Multilibs)
190193
if (!Multilib.isError())
191194
ss << "\n" << llvm::join(Multilib.flags(), " ");
192195
D.Diag(clang::diag::note_drv_available_multilibs) << ss.str();
196+
197+
// Now report any custom error messages requested by the YAML. We do
198+
// this after displaying the list of available multilibs, because
199+
// that list is probably large, and (in interactive use) risks
200+
// scrolling the useful error message off the top of the user's
201+
// terminal.
202+
for (const Multilib &Multilib : Result.SelectedMultilibs)
203+
if (Multilib.isError())
204+
D.Diag(clang::diag::err_drv_multilib_custom_error)
205+
<< Multilib.getErrorMessage();
206+
207+
// If there was an error, clear the SelectedMultilibs vector, in
208+
// case it contains partial data.
209+
Result.SelectedMultilibs.clear();
193210
}
194211

195212
static constexpr llvm::StringLiteral MultilibFilename = "multilib.yaml";

0 commit comments

Comments
 (0)