[Clang] Check enable_if attribute in the DC of current function (#175899)

A ContextRAII here ensures immediate access control checking within the
current context, allowing us to rule out inaccessible constructors
during potential overload resolution, where access diagnostics are
converted from hard errors into SFINAE errors, making the behavior more
preferrable with the nature of the enable_if attribute.

Fixes https://github.com/llvm/llvm-project/issues/175895
This commit is contained in:
Younan Zhang 2026-01-14 23:16:15 +08:00 committed by GitHub
parent 565c0e6529
commit 28009c8880
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 38 additions and 0 deletions

View File

@ -120,6 +120,7 @@ Bug Fixes to Compiler Builtins
Bug Fixes to Attribute Support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed a behavioral discrepancy between deleted functions and private members when checking the ``enable_if`` attribute. (#GH175895)
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -7551,6 +7551,8 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function,
return nullptr;
SFINAETrap Trap(*this);
// Switching the DC to ensure the immediate access control checking.
ContextRAII SavedContext(*this, Function->getDeclContext());
SmallVector<Expr *, 16> ConvertedArgs;
// FIXME: We should look into making enable_if late-parsed.
Expr *DiscardedThis;

View File

@ -562,6 +562,41 @@ namespace IgnoreUnusedArgSideEffects {
#endif
}
namespace GH175895 {
using int32_t = int;
struct wxuin_t {
wxuin_t() {}
wxuin_t(int32_t v) __attribute__((enable_if(v == 0, "Expect only constant expressions"))) {}
};
struct wxuin64_t {
wxuin64_t() {}
explicit operator wxuin_t() const { return {}; }
private:
operator int() const { return 0; }
};
struct wxuin64_t_deleted {
wxuin64_t_deleted() {}
explicit operator wxuin_t() const { return {}; }
operator int() = delete;
};
void main() {
wxuin64_t uin64{};
wxuin64_t_deleted deleted{};
auto b = static_cast<wxuin_t>(uin64);
auto c = static_cast<wxuin_t>(deleted);
}
}
namespace DefaultArgs {
void f(int n = __builtin_LINE()) __attribute__((enable_if(n == 12345, "only callable on line 12345"))); // expected-note {{only callable on line 12345}}
void g() { f(); } // expected-error {{no matching function}}