Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions include/swift/AST/DiagnosticEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,9 @@ namespace swift {

/// Don't emit any warnings
bool suppressWarnings = false;

/// Don't emit any notes
bool suppressNotes = false;

/// Don't emit any remarks
bool suppressRemarks = false;
Expand Down Expand Up @@ -663,6 +666,10 @@ namespace swift {
void setSuppressWarnings(bool val) { suppressWarnings = val; }
bool getSuppressWarnings() const { return suppressWarnings; }

/// Whether to skip emitting notes
void setSuppressNotes(bool val) { suppressNotes = val; }
bool getSuppressNotes() const { return suppressNotes; }

/// Whether to skip emitting remarks
void setSuppressRemarks(bool val) { suppressRemarks = val; }
bool getSuppressRemarks() const { return suppressRemarks; }
Expand Down Expand Up @@ -708,6 +715,7 @@ namespace swift {
void swap(DiagnosticState &other) {
std::swap(showDiagnosticsAfterFatalError, other.showDiagnosticsAfterFatalError);
std::swap(suppressWarnings, other.suppressWarnings);
std::swap(suppressNotes, other.suppressNotes);
std::swap(suppressRemarks, other.suppressRemarks);
std::swap(warningsAsErrors, other.warningsAsErrors);
std::swap(fatalErrorOccurred, other.fatalErrorOccurred);
Expand Down Expand Up @@ -904,6 +912,12 @@ namespace swift {
return state.getSuppressWarnings();
}

/// Whether to skip emitting notes
void setSuppressNotes(bool val) { state.setSuppressNotes(val); }
bool getSuppressNotes() const {
return state.getSuppressNotes();
}

/// Whether to skip emitting remarks
void setSuppressRemarks(bool val) { state.setSuppressRemarks(val); }
bool getSuppressRemarks() const {
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Basic/DiagnosticOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class DiagnosticOptions {
/// Suppress all warnings
bool SuppressWarnings = false;

/// Suppress all notes
bool SuppressNotes = false;

/// Suppress all remarks
bool SuppressRemarks = false;

Expand Down
2 changes: 1 addition & 1 deletion include/swift/Frontend/ModuleInterfaceLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ struct InterfaceSubContextDelegateImpl : InterfaceSubContextDelegate {
const LangOptions &LangOpts,
const ClangImporterOptions &clangImporterOpts,
const CASOptions &casOpts,
bool suppressRemarks);
bool suppressNotes, bool suppressRemarks);
bool extractSwiftInterfaceVersionAndArgs(CompilerInvocation &subInvocation,
DiagnosticEngine &subInstanceDiags,
SwiftInterfaceInfo &interfaceInfo,
Expand Down
4 changes: 4 additions & 0 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,10 @@ def Wwarning : Separate<["-"], "Wwarning">,
MetaVarName<"<diagnostic_group>">,
HelpText<"Treat this warning group as warning">;

def suppress_notes : Flag<["-"], "suppress-notes">,
Flags<[FrontendOption]>,
HelpText<"Suppress all notes">;

def suppress_remarks : Flag<["-"], "suppress-remarks">,
Flags<[FrontendOption]>,
HelpText<"Suppress all remarks">;
Expand Down
5 changes: 5 additions & 0 deletions lib/AST/DiagnosticEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,11 @@ DiagnosticState::determineBehavior(const Diagnostic &diag) const {
if (suppressWarnings)
lvl = DiagnosticBehavior::Ignore;
}

if (lvl == DiagnosticBehavior::Note) {
if (suppressNotes)
lvl = DiagnosticBehavior::Ignore;
}

if (lvl == DiagnosticBehavior::Remark) {
if (suppressRemarks)
Expand Down
44 changes: 30 additions & 14 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7300,10 +7300,8 @@ clang::FunctionDecl *ClangImporter::instantiateCXXFunctionTemplate(
// Instantiate a specialization of this template using the substitution map.
auto *templateArgList = clang::TemplateArgumentList::CreateCopy(
func->getASTContext(), templateSubst);
auto &sema = getClangInstance().getSema();
auto *spec = sema.InstantiateFunctionDeclaration(func, templateArgList,
clang::SourceLocation());
if (!spec) {

auto diagnoseSubstFail = [&]() {
std::string templateParams;
llvm::raw_string_ostream templateParamsStream(templateParams);
llvm::interleaveComma(templateArgList->asArray(), templateParamsStream,
Expand All @@ -7315,9 +7313,24 @@ clang::FunctionDecl *ClangImporter::instantiateCXXFunctionTemplate(
Impl.diagnose(HeaderLoc(func->getBeginLoc()),
diag::unable_to_substitute_cxx_function_template,
getFuncName(), templateParams);
};

auto &sema = getClangInstance().getSema();
auto *spec = sema.InstantiateFunctionDeclaration(func, templateArgList,
clang::SourceLocation());
if (!spec || spec->isInvalidDecl()) {
diagnoseSubstFail();
return nullptr;
}

sema.InstantiateFunctionDefinition(clang::SourceLocation(), spec);
// Even if the declaration can be instantiated, the definition may contain
// a substitution failure that renders spec invalid as a side-effect.
if (spec->isInvalidDecl()) {
diagnoseSubstFail();
return nullptr;
}

return spec;
}

Expand Down Expand Up @@ -7714,6 +7727,12 @@ ClangImporter::getCXXFunctionTemplateSpecialization(SubstitutionMap subst,
assert(isa<clang::FunctionTemplateDecl>(decl->getClangDecl()) &&
"This API should only be used with function templates.");

// If we hit some instantiation failure and expect the compiler to imminently
// terminate (with an error), return some reasonable-looking placeholder value
// in the meantime because callers expect this function to return some
// non-empty ConcreteDeclRef.
auto failurePlaceholder = [&]() { return ConcreteDeclRef(decl); };

auto *newFn =
decl->getASTContext()
.getClangModuleLoader()
Expand All @@ -7722,31 +7741,28 @@ ClangImporter::getCXXFunctionTemplateSpecialization(SubstitutionMap subst,
const_cast<clang::FunctionTemplateDecl *>(
cast<clang::FunctionTemplateDecl>(decl->getClangDecl())),
subst);
// We failed to specialize this function template. The compiler is going to
// exit soon. Return something valid in the meantime.
if (!newFn)
return ConcreteDeclRef(decl);
return failurePlaceholder();

auto [fnIt, inserted] =
Impl.specializedFunctionTemplates.try_emplace(newFn, nullptr);
if (!inserted)
return ConcreteDeclRef(fnIt->second);

auto newDecl = cast_or_null<ValueDecl>(
decl->getASTContext().getClangModuleLoader()->importDeclDirectly(
newFn));
auto *newDecl = cast_or_null<ValueDecl>(
decl->getASTContext().getClangModuleLoader()->importDeclDirectly(newFn));
if (!newDecl)
return failurePlaceholder();

if (auto fn = dyn_cast<AbstractFunctionDecl>(newDecl)) {
if (auto *fn = dyn_cast<AbstractFunctionDecl>(newDecl)) {
if (!subst.empty()) {
newDecl = rewriteIntegerTypes(subst, decl, fn);
}
}

if (auto fn = dyn_cast<FuncDecl>(decl)) {
if (auto *fn = dyn_cast<FuncDecl>(decl)) {
newDecl = addThunkForDependentTypes(fn, cast<FuncDecl>(newDecl));
}

if (auto fn = dyn_cast<FuncDecl>(decl)) {
if (newFn->getNumParams() != fn->getParameters()->size()) {
newDecl = generateThunkForExtraMetatypes(subst, fn,
cast<FuncDecl>(newDecl));
Expand Down
4 changes: 4 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2652,6 +2652,7 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
}

Opts.SuppressWarnings |= Args.hasArg(OPT_suppress_warnings);
Opts.SuppressNotes |= Args.hasArg(OPT_suppress_notes);
Opts.SuppressRemarks |= Args.hasArg(OPT_suppress_remarks);
for (const Arg *arg : Args.filtered(OPT_warning_treating_Group)) {
Opts.WarningsAsErrorsRules.push_back([&] {
Expand Down Expand Up @@ -2732,6 +2733,9 @@ static void configureDiagnosticEngine(
if (Options.SuppressWarnings) {
Diagnostics.setSuppressWarnings(true);
}
if (Options.SuppressNotes) {
Diagnostics.setSuppressNotes(true);
}
if (Options.SuppressRemarks) {
Diagnostics.setSuppressRemarks(true);
}
Expand Down
9 changes: 8 additions & 1 deletion lib/Frontend/ModuleInterfaceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1663,7 +1663,7 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
FrontendOptions::ActionType requestedAction,
const SearchPathOptions &SearchPathOpts, const LangOptions &LangOpts,
const ClangImporterOptions &clangImporterOpts, const CASOptions &casOpts,
bool suppressRemarks) {
bool suppressNotes, bool suppressRemarks) {
GenericArgs.push_back("-frontend");
// Start with a genericSubInvocation that copies various state from our
// invoking ASTContext.
Expand Down Expand Up @@ -1752,6 +1752,12 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
genericSubInvocation.getDiagnosticOptions().SuppressWarnings = true;
GenericArgs.push_back("-suppress-warnings");

// Inherit the parent invocation's setting on whether to suppress remarks
if (suppressNotes) {
genericSubInvocation.getDiagnosticOptions().SuppressNotes = true;
GenericArgs.push_back("-suppress-notes");
}

// Inherit the parent invocation's setting on whether to suppress remarks
if (suppressRemarks) {
genericSubInvocation.getDiagnosticOptions().SuppressRemarks = true;
Expand Down Expand Up @@ -1863,6 +1869,7 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
genericSubInvocation.setMainExecutablePath(LoaderOpts.mainExecutablePath);
inheritOptionsForBuildingInterface(LoaderOpts.requestedAction, searchPathOpts,
langOpts, clangImporterOpts, casOpts,
Diags->getSuppressNotes(),
Diags->getSuppressRemarks());
// Configure front-end input.
auto &SubFEOpts = genericSubInvocation.getFrontendOptions();
Expand Down
44 changes: 44 additions & 0 deletions test/Interop/Cxx/templates/static-cast-typecheck.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: split-file %s %t
// RUN: %target-swift-frontend -typecheck -verify -suppress-remarks -suppress-notes \
// RUN: -cxx-interoperability-mode=default \
// RUN: -I %t%{fs-sep}Inputs %t%{fs-sep}main.swift \
// RUN: -verify-additional-file %t%{fs-sep}Inputs%{fs-sep}header.h

//--- Inputs/module.modulemap
module CxxHeader {
header "header.h"
requires cplusplus
}

//--- Inputs/header.h
#pragma once

// TODO: the following diagnostics should be moved to main.swift at the call site
// that triggers the instantiation
// expected-error@+4 {{could not substitute parameters for C++ function template 'cxxCast': BaseT, UnrelatedT}}
// expected-error@+3 {{could not substitute parameters for C++ function template 'cxxCast': BaseT, SubClassT}}
// expected-error@+2 {{could not substitute parameters for C++ function template 'cxxCast': BaseT, SubProtectedT}}
// expected-error@+1 {{could not substitute parameters for C++ function template 'cxxCast': BaseT, SubPrivateT}}
template <class O, class I> O cxxCast(I i) { return static_cast<O>(i); }
// expected-error@-1 {{cannot cast 'const SubPrivateT' to its private base class 'const BaseT'}}
// expected-error@-2 {{cannot cast 'const SubProtectedT' to its protected base class 'const BaseT'}}
// expected-error@-3 {{cannot cast 'const SubClassT' to its private base class 'const BaseT'}}
// expected-error@-4 {{no matching conversion for static_cast from 'UnrelatedT' to 'BaseT'}}

struct BaseT { };

struct SubT : BaseT { }; // publicly inherit from BaseT
struct SubPrivateT : private BaseT { }; // privately inherit from BaseT
struct SubProtectedT : protected BaseT { }; // privately inherit from BaseT
class SubClassT : BaseT { }; // privately inherit from BaseT
struct UnrelatedT { }; // does not inherit from BaseT


//--- main.swift
import CxxHeader

let _: BaseT = cxxCast(SubT()) // valid: upcast to public base
let _: BaseT = cxxCast(SubPrivateT()) // invalid: upcast to non-public base
let _: BaseT = cxxCast(SubProtectedT()) // invalid: upcast to non-public base
let _: BaseT = cxxCast(SubClassT()) // invalid: upcast to non-public base
let _: BaseT = cxxCast(UnrelatedT()) // invalid: cast to unrelated type