Skip to content

[clang]improve diagnosing redefined defaulted constructor with different exception specs #69688

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 25, 2023
Merged
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
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ Improvements to Clang's diagnostics
| ~~~~~~~~~^~~~~~~~
- Clang now always diagnoses when using non-standard layout types in ``offsetof`` .
(`#64619: <https://github.com/llvm/llvm-project/issues/64619>`_)
- Clang now diagnoses redefined defaulted constructor when redefined
defaulted constructor with different exception specs.
(`#69094: <https://github.com/llvm/llvm-project/issues/69094>`_)
- Clang now diagnoses use of variable-length arrays in C++ by default (and
under ``-Wall`` in GNU++ mode). This is an extension supported by Clang and
GCC, but is very easy to accidentally use without realizing it's a
Expand Down
25 changes: 13 additions & 12 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3922,18 +3922,6 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S,
}

if (getLangOpts().CPlusPlus) {
// C++1z [over.load]p2
// Certain function declarations cannot be overloaded:
// -- Function declarations that differ only in the return type,
// the exception specification, or both cannot be overloaded.

// Check the exception specifications match. This may recompute the type of
// both Old and New if it resolved exception specifications, so grab the
// types again after this. Because this updates the type, we do this before
// any of the other checks below, which may update the "de facto" NewQType
// but do not necessarily update the type of New.
if (CheckEquivalentExceptionSpec(Old, New))
return true;
OldQType = Context.getCanonicalType(Old->getType());
NewQType = Context.getCanonicalType(New->getType());

Expand Down Expand Up @@ -4055,6 +4043,19 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S,
}
}

// C++1z [over.load]p2
// Certain function declarations cannot be overloaded:
// -- Function declarations that differ only in the return type,
// the exception specification, or both cannot be overloaded.

// Check the exception specifications match. This may recompute the type of
// both Old and New if it resolved exception specifications, so grab the
// types again after this. Because this updates the type, we do this before
// any of the other checks below, which may update the "de facto" NewQType
// but do not necessarily update the type of New.
if (CheckEquivalentExceptionSpec(Old, New))
return true;

// C++11 [dcl.attr.noreturn]p1:
// The first declaration of a function shall specify the noreturn
// attribute if any declaration of that function specifies the noreturn
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fcxx-exceptions -std=c++11 %s

struct ExplicitlySpecialMethod {
ExplicitlySpecialMethod() = default;
};
ExplicitlySpecialMethod::ExplicitlySpecialMethod() {} // expected-error{{definition of explicitly defaulted default constructor}}

struct ImplicitlySpecialMethod {};
ImplicitlySpecialMethod::ImplicitlySpecialMethod() {} // expected-error{{definition of implicitly declared default constructor}}