mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 09:06:43 +00:00
[Clang][Interp] Fix the location of uninitialized base warning (#100761)
Fix the location of `diag::note_constexpr_uninitialized_base`, make it same as current interpreter. This PR does not print type name with namespacethat was used to improve the current interpreter's type dump of base class type. --------- Signed-off-by: yronglin <yronglin777@gmail.com>
This commit is contained in:
parent
f395d826bf
commit
6434dce85d
@ -10,7 +10,9 @@
|
||||
#include "InterpState.h"
|
||||
#include "Record.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include <iterator>
|
||||
|
||||
namespace clang {
|
||||
namespace interp {
|
||||
@ -122,19 +124,18 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc,
|
||||
}
|
||||
|
||||
// Check Fields in all bases
|
||||
for (const Record::Base &B : R->bases()) {
|
||||
for (auto [I, B] : llvm::enumerate(R->bases())) {
|
||||
Pointer P = BasePtr.atField(B.Offset);
|
||||
if (!P.isInitialized()) {
|
||||
const Descriptor *Desc = BasePtr.getDeclDesc();
|
||||
if (Desc->asDecl())
|
||||
S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(),
|
||||
diag::note_constexpr_uninitialized_base)
|
||||
if (const auto *CD = dyn_cast_if_present<CXXRecordDecl>(R->getDecl())) {
|
||||
const auto &BS = *std::next(CD->bases_begin(), I);
|
||||
S.FFDiag(BS.getBaseTypeLoc(), diag::note_constexpr_uninitialized_base)
|
||||
<< B.Desc->getType() << BS.getSourceRange();
|
||||
} else {
|
||||
S.FFDiag(Desc->getLocation(), diag::note_constexpr_uninitialized_base)
|
||||
<< B.Desc->getType();
|
||||
else
|
||||
S.FFDiag(BasePtr.getDeclDesc()->asExpr()->getExprLoc(),
|
||||
diag::note_constexpr_uninitialized_base)
|
||||
<< B.Desc->getType();
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Result &= CheckFieldsInitialized(S, Loc, P, B.R);
|
||||
|
@ -5,8 +5,6 @@
|
||||
/// Differences:
|
||||
/// 1) The type of the uninitialized base class is printed WITH the namespace,
|
||||
/// i.e. 'baseclass_uninit::DelBase' instead of just 'DelBase'.
|
||||
/// 2) The location is not the base specifier declaration, but the call site
|
||||
/// of the constructor.
|
||||
|
||||
|
||||
namespace baseclass_uninit {
|
||||
@ -14,33 +12,29 @@ struct DelBase {
|
||||
constexpr DelBase() = delete; // expected-note {{'DelBase' has been explicitly marked deleted here}}
|
||||
};
|
||||
|
||||
struct Foo : DelBase {
|
||||
struct Foo : DelBase { // expected-note 2{{constructor of base class 'baseclass_uninit::DelBase' is not called}}
|
||||
constexpr Foo() {}; // expected-error {{call to deleted constructor of 'DelBase'}}
|
||||
};
|
||||
constexpr Foo f; // expected-error {{must be initialized by a constant expression}} \
|
||||
// expected-note {{constructor of base class 'baseclass_uninit::DelBase' is not called}}
|
||||
constexpr Foo f; // expected-error {{must be initialized by a constant expression}}
|
||||
|
||||
struct Bar : Foo {
|
||||
constexpr Bar() {};
|
||||
};
|
||||
constexpr Bar bar; // expected-error {{must be initialized by a constant expression}} \
|
||||
// expected-note {{constructor of base class 'baseclass_uninit::DelBase' is not called}}
|
||||
constexpr Bar bar; // expected-error {{must be initialized by a constant expression}}
|
||||
|
||||
struct Base {};
|
||||
struct A : Base {
|
||||
struct A : Base { // expected-note {{constructor of base class 'baseclass_uninit::Base' is not called}}
|
||||
constexpr A() : value() {} // expected-error {{member initializer 'value' does not name a non-static data member or base class}}
|
||||
};
|
||||
|
||||
constexpr A a; // expected-error {{must be initialized by a constant expression}} \
|
||||
// expected-note {{constructor of base class 'baseclass_uninit::Base' is not called}}
|
||||
constexpr A a; // expected-error {{must be initialized by a constant expression}}
|
||||
|
||||
|
||||
struct B : Base {
|
||||
struct B : Base { // expected-note {{constructor of base class 'baseclass_uninit::Base' is not called}}
|
||||
constexpr B() : {} // expected-error {{expected class member or base class name}}
|
||||
};
|
||||
|
||||
constexpr B b; // expected-error {{must be initialized by a constant expression}} \
|
||||
// expected-note {{constructor of base class 'baseclass_uninit::Base' is not called}}
|
||||
constexpr B b; // expected-error {{must be initialized by a constant expression}}
|
||||
} // namespace baseclass_uninit
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// RUN: %clang_cc1 -std=c23 -verify -triple x86_64 -pedantic -Wno-conversion -Wno-constant-conversion %s
|
||||
// RUN: %clang_cc1 -std=c23 -verify -triple x86_64 -pedantic -Wno-conversion -Wno-constant-conversion -fexperimental-new-constant-interpreter %s
|
||||
|
||||
/* WG14 N3018: Full
|
||||
* The constexpr specifier for object definitions
|
||||
|
@ -1,4 +1,5 @@
|
||||
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 %s -fexperimental-new-constant-interpreter -emit-llvm -o - | FileCheck %s
|
||||
// PR 3518
|
||||
// Some of the objects were coming out as uninitialized (external) before 3518
|
||||
// was fixed. Internal names are different between llvm-gcc and clang so they
|
||||
|
@ -4,6 +4,8 @@
|
||||
// RUN: printf "\0" > %t/null_byte.bin
|
||||
// RUN: %clang_cc1 %s -fsyntax-only --embed-dir=%t -verify=expected,cxx -Wno-c23-extensions
|
||||
// RUN: %clang_cc1 -x c -std=c23 %s -fsyntax-only --embed-dir=%t -verify=expected,c
|
||||
// RUN: %clang_cc1 %s -fsyntax-only -fexperimental-new-constant-interpreter --embed-dir=%t -verify=expected,cxx -Wno-c23-extensions
|
||||
// RUN: %clang_cc1 -x c -std=c23 %s -fsyntax-only -fexperimental-new-constant-interpreter --embed-dir=%t -verify=expected,c
|
||||
#embed <media/empty>
|
||||
;
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
|
||||
|
||||
namespace baseclass_uninit {
|
||||
struct DelBase {
|
||||
constexpr DelBase() = delete; // expected-note {{'DelBase' has been explicitly marked deleted here}}
|
||||
};
|
||||
|
||||
struct Foo : DelBase { // expected-note 2{{constructor of base class 'DelBase' is not called}}
|
||||
struct Foo : DelBase { // expected-note-re 2{{constructor of base class '{{.*}}DelBase' is not called}}
|
||||
constexpr Foo() {}; // expected-error {{call to deleted constructor of 'DelBase'}}
|
||||
};
|
||||
constexpr Foo f; // expected-error {{must be initialized by a constant expression}}
|
||||
@ -15,13 +16,13 @@ struct Bar : Foo {
|
||||
constexpr Bar bar; // expected-error {{must be initialized by a constant expression}}
|
||||
|
||||
struct Base {};
|
||||
struct A : Base { // expected-note {{constructor of base class 'Base' is not called}}
|
||||
struct A : Base { // expected-note-re {{constructor of base class '{{.*}}Base' is not called}}
|
||||
constexpr A() : value() {} // expected-error {{member initializer 'value' does not name a non-static data member or base class}}
|
||||
};
|
||||
|
||||
constexpr A a; // expected-error {{must be initialized by a constant expression}}
|
||||
|
||||
struct B : Base { // expected-note {{constructor of base class 'Base' is not called}}
|
||||
struct B : Base { // expected-note-re {{constructor of base class '{{.*}}Base' is not called}}
|
||||
constexpr B() : {} // expected-error {{expected class member or base class name}}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user