llvm-project/clang/test/SemaCXX/exception-spec.cpp
Younan Zhang 2c2ad9a096
Reapply "[Clang] Profile singly-resolved UnresolvedLookupExpr with the declaration" (#140680)
For a dependent variable template specialization, we don't build a
dependent Decl node or a DeclRefExpr to represent it. Instead, we
preserve the UnresolvedLookupExpr until instantiation.

However, this approach isn't ideal for constraint normalization. We
consider the qualifier during profiling, but since that's based on the
written code, it can introduce confusing differences, even when the
expressions resolve to the same declaration.

This change profiles the underlying VarTemplateDecl if
UnresolvedLookupExpr is used to model a dependent use of it.

Fixes https://github.com/llvm/llvm-project/issues/139476
2025-06-19 14:59:32 +08:00

76 lines
2.0 KiB
C++

// RUN: %clang_cc1 -fsyntax-only -verify -fcxx-exceptions -std=c++11 %s
namespace MissingOnTemplate {
template<typename T> void foo(T) noexcept(true); // expected-note {{previous}}
template<typename T> void foo(T); // expected-error {{missing exception specification 'noexcept(true)'}}
void test() { foo(0); }
}
struct UseBeforeComplete1 {
~UseBeforeComplete1(); // expected-note {{previous}}
struct X {
friend UseBeforeComplete1::~UseBeforeComplete1() noexcept; // expected-warning {{previously declared with an implicit}}
};
};
struct ThrowingDtor { ~ThrowingDtor() noexcept(false); };
struct UseBeforeComplete2 {
~UseBeforeComplete2(); // expected-note {{previous}}
struct X {
friend UseBeforeComplete2::~UseBeforeComplete2() noexcept; // expected-error {{does not match previous}}
};
ThrowingDtor td;
};
struct UseBeforeComplete3 {
~UseBeforeComplete3();
struct X {
friend UseBeforeComplete3::~UseBeforeComplete3(); // ok, implicitly noexcept(true)
};
};
static_assert(noexcept(UseBeforeComplete3()), "");
struct UseBeforeComplete4 {
~UseBeforeComplete4();
struct X {
friend UseBeforeComplete4::~UseBeforeComplete4(); // ok, implicitly noexcept(false)
};
ThrowingDtor td;
};
static_assert(!noexcept(UseBeforeComplete4()), "");
namespace AssignmentOp {
struct D1;
struct D2;
struct B {
B &operator=(const B&);
virtual D1 &operator=(const D1&) noexcept; // expected-note {{overridden}}
virtual D2 &operator=(const D2&) noexcept; // expected-note {{overridden}}
};
struct D1 : B {}; // expected-error {{more lax}}
struct D2 : B {
D2 &operator=(const D2&); // expected-error {{more lax}}
};
}
namespace OverloadedFunctions {
template <typename T>
void f(T&) noexcept;
template <typename T, int N>
void f(T (&arr)[N]) noexcept(noexcept(f(*arr)));
template <typename T>
inline void f(T&) noexcept {}
template <typename T, int N>
inline void f(T (&arr)[N]) noexcept(noexcept(f(*arr))) {}
void g() {
int x[1];
f(x);
}
}