[clang] [C++26][clang] Implement P2795R5 'Erroneous behaviour for uninitialized reads' (PR #177614)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 23 09:01:16 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
Author: None (yronglin)
<details>
<summary>Changes</summary>
This patch implement [P2795R5 'Erroneous behaviour for uninitialized reads'](https://wg21.link/p2795r5).
In C++26, reading from an uninitialized automatic storage duration variable is no longer undefined behavior, since P2795R5, it's a defined erroneous behavior.
- Add `[[indeterminate]]` standard attribute to opt-out of erroneous initialization (restore UB)
- Add `APValue::Erroneous` to track erroneous values in constant expression evaluation
- Reject erroneous values in constant expressions (same as indeterminate)
- Add `-Werroneous-behavior` diagnostic group for runtime warnings
- Support `[[indeterminate]]` on local variables and function parameters
---
Patch is 33.70 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/177614.diff
26 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+1)
- (modified) clang/include/clang/AST/APValue.h (+17-1)
- (modified) clang/include/clang/AST/PropertiesBase.td (+3)
- (modified) clang/include/clang/Basic/Attr.td (+22)
- (modified) clang/include/clang/Basic/AttrDocs.td (+34)
- (modified) clang/include/clang/Basic/DiagnosticGroups.td (+1)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+13)
- (modified) clang/lib/AST/APValue.cpp (+3)
- (modified) clang/lib/AST/ASTImporter.cpp (+1)
- (modified) clang/lib/AST/Expr.cpp (+1)
- (modified) clang/lib/AST/ExprConstant.cpp (+8-3)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+2)
- (modified) clang/lib/AST/MicrosoftMangle.cpp (+1)
- (modified) clang/lib/AST/TextNodeDumper.cpp (+4)
- (modified) clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp (+3-1)
- (modified) clang/lib/CodeGen/CGDecl.cpp (+5)
- (modified) clang/lib/CodeGen/CGExprConstant.cpp (+3)
- (modified) clang/lib/Sema/AnalysisBasedWarnings.cpp (+29-1)
- (modified) clang/lib/Sema/SemaDecl.cpp (+23)
- (modified) clang/lib/Sema/SemaTemplate.cpp (+1)
- (added) clang/test/CodeGenCXX/cxx26-indeterminate-attribute.cpp (+82)
- (added) clang/test/SemaCXX/cxx26-erroneous-behavior-warning.cpp (+29)
- (added) clang/test/SemaCXX/cxx26-erroneous-constexpr.cpp (+55)
- (added) clang/test/SemaCXX/cxx26-indeterminate-attribute.cpp (+66)
- (modified) clang/utils/TableGen/ClangAttrEmitter.cpp (+1-1)
- (modified) clang/www/cxx_status.html (+1-1)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..92ece34adefff 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -81,6 +81,7 @@ C++ Language Changes
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
+- Clang now supports `P2795R5 <https://wg21.link/p2795r5>`_ Erroneous behaviour for uninitialized reads.
C++23 Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h
index 8a2d6d434792a..620cbf2fe09e4 100644
--- a/clang/include/clang/AST/APValue.h
+++ b/clang/include/clang/AST/APValue.h
@@ -129,6 +129,15 @@ class APValue {
None,
/// This object has an indeterminate value (C++ [basic.indet]).
Indeterminate,
+
+ /// [defns.erroneous]:
+ /// Erroneous behavior is always the consequence of incorrectprogram code.
+ /// Implementations are allowed, but not required, to diagnose it
+ /// ([intro.compliance.general]). Evaluation of a constant expression
+ /// ([expr.const]) never exhibits behavior specified as erroneous in [intro]
+ /// through [cpp].
+ /// Reading it has erroneous behavior but the value is well-defined.
+ Erroneous,
Int,
Float,
FixedPoint,
@@ -435,11 +444,17 @@ class APValue {
return Result;
}
+ static APValue ErroneousValue() {
+ APValue Result;
+ Result.Kind = Erroneous;
+ return Result;
+ }
+
APValue &operator=(const APValue &RHS);
APValue &operator=(APValue &&RHS);
~APValue() {
- if (Kind != None && Kind != Indeterminate)
+ if (Kind != None && Kind != Indeterminate && Kind != Erroneous)
DestroyDataAndMakeUninit();
}
@@ -462,6 +477,7 @@ class APValue {
bool isAbsent() const { return Kind == None; }
bool isIndeterminate() const { return Kind == Indeterminate; }
+ bool isErroneous() const { return Kind == Erroneous; }
bool hasValue() const { return Kind != None && Kind != Indeterminate; }
bool isInt() const { return Kind == Int; }
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 5b10127526e4e..3ea1be6bbbd18 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -266,6 +266,9 @@ let Class = PropertyTypeCase<APValue, "None"> in {
let Class = PropertyTypeCase<APValue, "Indeterminate"> in {
def : Creator<[{ return APValue::IndeterminateValue(); }]>;
}
+let Class = PropertyTypeCase<APValue, "Erroneous"> in {
+ def : Creator<[{ return APValue::ErroneousValue(); }]>;
+}
let Class = PropertyTypeCase<APValue, "Int"> in {
def : Property<"value", APSInt> {
let Read = [{ node.getInt() }];
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index ba44266d22c8c..aaa5e04effebe 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -100,6 +100,9 @@ class SubsetSubject<AttrSubject base, code check, string diag> : AttrSubject {
def LocalVar : SubsetSubject<Var,
[{S->hasLocalStorage() && !isa<ParmVarDecl>(S)}],
"local variables">;
+def AutomaticStorageVar : SubsetSubject<Var,
+ [{S->hasLocalStorage()}],
+ "local variables or function parameters">;
def NonParmVar : SubsetSubject<Var,
[{S->getKind() != Decl::ParmVar}],
"variables">;
@@ -350,6 +353,10 @@ class CXX11<string namespace, string name, int version = 1>
: Spelling<name, "CXX11", version> {
string Namespace = namespace;
}
+class CXX26<string namespace, string name, int version = 1>
+ : Spelling<name, "CXX26", version> {
+ string Namespace = namespace;
+}
class C23<string namespace, string name, int version = 1>
: Spelling<name, "C23", version> {
string Namespace = namespace;
@@ -432,6 +439,7 @@ def SYCLHost : LangOpt<"SYCLIsHost">;
def SYCLDevice : LangOpt<"SYCLIsDevice">;
def COnly : LangOpt<"", "!LangOpts.CPlusPlus">;
def CPlusPlus : LangOpt<"CPlusPlus">;
+def CPlusPlus26 : LangOpt<"CPlusPlus26">;
def OpenCL : LangOpt<"OpenCL">;
def ObjC : LangOpt<"ObjC">;
def BlocksSupported : LangOpt<"Blocks">;
@@ -4827,6 +4835,20 @@ def Uninitialized : InheritableAttr {
let Documentation = [UninitializedDocs];
}
+// [dcl.attr.indet]/p1:
+// The attribute-token indeterminate may be applied to the definition of a block variable
+// with automatic storage duration or to a parameter-declaration of a function declaration.
+// No attribute-argument-clause shall be present. The attribute specifies that the storage
+// of an object with automatic storage duration is initially indeterminate rather than
+// erroneous ([basic.indet]).
+def Indeterminate : InheritableAttr {
+ let Spellings = [CXX11<"", "indeterminate", 202403>];
+ let Subjects = SubjectList<[AutomaticStorageVar]>;
+ let LangOpts = [CPlusPlus26];
+ let Documentation = [IndeterminateDocs];
+ let SimpleHandler = 1;
+}
+
def LoaderUninitialized : Attr {
let Spellings = [Clang<"loader_uninitialized">];
let Subjects = SubjectList<[GlobalVar]>;
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 812b48058d189..edf1452e25717 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7205,6 +7205,40 @@ it rather documents the programmer's intent.
}];
}
+def IndeterminateDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The ``[[indeterminate]]`` attribute is a C++26 standard attribute (P2795R5)
+that can be applied to the definition of a block variable with automatic
+storage duration or to a function parameter declaration.
+
+In C++26, reading from an uninitialized variable has *erroneous behavior*
+rather than undefined behavior. Variables are implicitly initialized with
+implementation-defined values. The ``[[indeterminate]]`` attribute opts out
+of this erroneous initialization, restoring the previous behavior where the
+variable has an *indeterminate value* and reading it causes undefined behavior.
+
+This attribute is intended for performance-critical code where the overhead
+of automatic initialization is unacceptable. Use with caution, as reading
+from such variables before proper initialization causes undefined behavior.
+
+.. code-block:: c++
+
+ void example() {
+ int x [[indeterminate]]; // x has indeterminate value (not erroneous)
+ int y; // y has erroneous value (reading is erroneous behavior)
+
+ // Reading x before initialization is undefined behavior
+ // Reading y before initialization is erroneous behavior
+ }
+
+ void f([[indeterminate]] int param); // param has indeterminate value
+
+If a function parameter is declared with the ``[[indeterminate]]`` attribute,
+it must be so declared in the first declaration of its function.
+ }];
+}
+
def LoaderUninitializedDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 34624dd3eed3a..027ddb35a6464 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -982,6 +982,7 @@ def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
UninitializedStaticSelfInit,
UninitializedConstReference,
UninitializedConstPointer]>;
+def ErroneousBehavior : DiagGroup<"erroneous-behavior">;
def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
// #pragma optimize is often used to avoid to work around MSVC codegen bugs or
// to disable inlining. It's not completely clear what alternative to suggest
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a2be7ab3791b9..9de87275d6c0b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2567,6 +2567,19 @@ def warn_uninit_const_pointer : Warning<
"variable %0 is uninitialized when passed as a const pointer argument here">,
InGroup<UninitializedConstPointer>, DefaultIgnore;
+def warn_erroneous_behavior_uninitialized_read : Warning<
+ "reading from variable %0 with erroneous value is erroneous behavior">,
+ InGroup<ErroneousBehavior>, DefaultIgnore;
+def note_variable_erroneous_init : Note<
+ "variable %0 was default-initialized here; "
+ "consider using '[[indeterminate]]' attribute to opt out">;
+def err_indeterminate_attr_not_on_first_decl : Error<
+ "'[[indeterminate]]' attribute on parameter %0 must appear on the "
+ "first declaration of the function">;
+def err_indeterminate_attr_mismatch : Error<
+ "'[[indeterminate]]' attribute on parameter %0 does not match "
+ "previous declaration">;
+
def warn_unsequenced_mod_mod : Warning<
"multiple unsequenced modifications to %0">, InGroup<Unsequenced>;
def warn_unsequenced_mod_use : Warning<
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
index 2e1c8eb3726cf..1aed1ea610b85 100644
--- a/clang/lib/AST/APValue.cpp
+++ b/clang/lib/AST/APValue.cpp
@@ -724,6 +724,8 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy,
case APValue::Indeterminate:
Out << "<uninitialized>";
return;
+ case APValue::Erroneous:
+ Out << "<erroneous>";
case APValue::Int:
if (Ty->isBooleanType())
Out << (getInt().getBoolValue() ? "true" : "false");
@@ -1133,6 +1135,7 @@ LinkageInfo LinkageComputer::getLVForValue(const APValue &V,
switch (V.getKind()) {
case APValue::None:
case APValue::Indeterminate:
+ case APValue::Erroneous:
case APValue::Int:
case APValue::Float:
case APValue::FixedPoint:
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 101ab2c40973b..f190950fc707b 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -10601,6 +10601,7 @@ ASTNodeImporter::ImportAPValue(const APValue &FromValue) {
switch (FromValue.getKind()) {
case APValue::None:
case APValue::Indeterminate:
+ case APValue::Erroneous:
case APValue::Int:
case APValue::Float:
case APValue::FixedPoint:
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 4bb979e51b75d..143024ea7b11e 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -302,6 +302,7 @@ ConstantResultStorageKind ConstantExpr::getStorageKind(const APValue &Value) {
switch (Value.getKind()) {
case APValue::None:
case APValue::Indeterminate:
+ case APValue::Erroneous:
return ConstantResultStorageKind::None;
case APValue::Int:
if (!Value.getInt().needsCleanup())
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 857688ed8039d..9ebd45eb77bcb 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2694,6 +2694,7 @@ static bool HandleConversionToBool(const APValue &Val, bool &Result) {
switch (Val.getKind()) {
case APValue::None:
case APValue::Indeterminate:
+ case APValue::Erroneous:
return false;
case APValue::Int:
Result = Val.getInt().getBoolValue();
@@ -4251,9 +4252,11 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
// Walk the designator's path to find the subobject.
for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) {
- // Reading an indeterminate value is undefined, but assigning over one is OK.
+ // Reading an indeterminate value is undefined, but assigning over one is
+ // OK. Reading an erroneous value is erroneous behavior also not allowed in
+ // constant expressions.
if ((O->isAbsent() && !(handler.AccessKind == AK_Construct && I == N)) ||
- (O->isIndeterminate() &&
+ ((O->isIndeterminate() || O->isErroneous()) &&
!isValidIndeterminateAccess(handler.AccessKind))) {
// Object has ended lifetime.
// If I is non-zero, some subobject (member or array element) of a
@@ -4263,7 +4266,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
return false;
if (!Info.checkingPotentialConstantExpression())
Info.FFDiag(E, diag::note_constexpr_access_uninit)
- << handler.AccessKind << O->isIndeterminate()
+ << handler.AccessKind << (O->isIndeterminate() || O->isErroneous())
<< E->getSourceRange();
return handler.failed();
}
@@ -5062,6 +5065,7 @@ struct CompoundAssignSubobjectHandler {
case APValue::Vector:
return foundVector(Subobj, SubobjType);
case APValue::Indeterminate:
+ case APValue::Erroneous:
Info.FFDiag(E, diag::note_constexpr_access_uninit)
<< /*read of=*/0 << /*uninitialized object=*/1
<< E->getLHS()->getSourceRange();
@@ -7828,6 +7832,7 @@ class APValueToBufferConverter {
// Dig through Src to find the byte at SrcOffset.
switch (Val.getKind()) {
case APValue::Indeterminate:
+ case APValue::Erroneous:
case APValue::None:
return true;
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index fa28c0d444cc4..65c770a6589ce 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -6411,6 +6411,7 @@ static bool isZeroInitialized(QualType T, const APValue &V) {
switch (V.getKind()) {
case APValue::None:
case APValue::Indeterminate:
+ case APValue::Erroneous:
case APValue::AddrLabelDiff:
return false;
@@ -6564,6 +6565,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
switch (V.getKind()) {
case APValue::None:
case APValue::Indeterminate:
+ case APValue::Erroneous:
Out << 'L';
mangleType(T);
Out << 'E';
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 551aa7bf3321c..73f0c52163d19 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1940,6 +1940,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
switch (V.getKind()) {
case APValue::None:
case APValue::Indeterminate:
+ case APValue::Erroneous:
// FIXME: MSVC doesn't allow this, so we can't be sure how it should be
// mangled.
if (WithScalarType)
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 7bc0404db1bee..898582aa4287e 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -608,6 +608,7 @@ static bool isSimpleAPValue(const APValue &Value) {
switch (Value.getKind()) {
case APValue::None:
case APValue::Indeterminate:
+ case APValue::Erroneous:
case APValue::Int:
case APValue::Float:
case APValue::FixedPoint:
@@ -682,6 +683,9 @@ void TextNodeDumper::Visit(const APValue &Value, QualType Ty) {
case APValue::Indeterminate:
OS << "Indeterminate";
return;
+ case APValue::Erroneous:
+ OS << "Erroneous";
+ return;
case APValue::Int:
OS << "Int ";
{
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index ecb65d901de54..795dd7caafba8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1783,7 +1783,9 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
switch (value.getKind()) {
case APValue::None:
case APValue::Indeterminate:
- cgm.errorNYI("ConstExprEmitter::tryEmitPrivate none or indeterminate");
+ case APValue::Erroneous:
+ cgm.errorNYI(
+ "ConstExprEmitter::tryEmitPrivate none, indeterminate or erroneous");
return {};
case APValue::Int: {
mlir::Type ty = cgm.convertType(destType);
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 8b1cd83af2396..0378b249bbf1d 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1980,9 +1980,14 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
auto hasNoTrivialAutoVarInitAttr = [&](const Decl *D) {
return D && D->hasAttr<NoTrivialAutoVarInitAttr>();
};
+
+ // C++26 [[indeterminate]] attribute opts out of an erroneous
+ // initialization, restoring indeterminate (undefined) behavior.
+
// Note: constexpr already initializes everything correctly.
LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =
((D.isConstexpr() || D.getAttr<UninitializedAttr>() ||
+ D.hasAttr<IndeterminateAttr>() ||
hasNoTrivialAutoVarInitAttr(type->getAsTagDecl()) ||
hasNoTrivialAutoVarInitAttr(CurFuncDecl))
? LangOptions::TrivialAutoVarInitKind::Uninitialized
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 0eec4dba4824a..e19982522f8cb 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -2441,7 +2441,10 @@ ConstantEmitter::tryEmitPrivate(const APValue &Value, QualType DestType,
switch (Value.getKind()) {
case APValue::None:
case APValue::Indeterminate:
+ case APValue::Erroneous:
// Out-of-lifetime and indeterminate values can be modeled as 'undef'.
+ // For C++ erroneous values, runtime code generation uses a defined pattern,
+ // but for constant expression failures we use undef.
return llvm::UndefValue::get(CGM.getTypes().ConvertType(DestType));
case APValue::LValue:
return ConstantLValueEmitter(*this, Value, DestType,
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 03d84fc935b8e..ab14bf6a458f8 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -976,8 +976,34 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
bool IsCapturedByBlock) {
bool Diagnosed = false;
+ // [basic.indet]/p1.1:
+ // - If the object has dynamic storage duration, or is the object associated
+ // with a variable or function parameter whose first declaration is marked
+ // with the [[indeterminate]] attribute ([dcl.attr.indet]), the bytes have
+ // indeterminate values;
+ //
+ // - otherwise, the bytes have erroneous values, where each value is
+ // determined
+ // by the implementation independently of the state of the program.
+ //
+ // If variable has automatic storage duration and does
+ // not have [[indeterminate]], reading it is erroneous behavior (not
+ // undefined). However, we still warn about it.
+ bool IsErroneousBehavior = S.getLangOpts().CPlusPlus26 &&
+ VD->hasLocalStorage() &&
+ !VD->hasAttr<IndeterminateAttr>();
switch (Use.getKind()) {
case UninitUse::Always:
+ if (IsErroneousBehavior &&
+ !S.Diags.isIgnored(diag::warn_erroneous_behavior_uninitialized_read,
+ Use.getUser()->getBeginLoc())) {
+ S.Diag(Use.getUser()->getBeginLoc(),
+ diag::warn_erroneous_behavior_uninitialized_read)
+ << VD->getDeclName() << Use.getUser()->getSourceRange();
+ S.Diag(VD->getLocation(), diag::note_variable_erroneous_init)
+ << VD->getDeclName();
+ return;
+ }
S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_var)
<< VD->getDeclName() << IsCapturedByBlock
<< Use.getUser()->getSourceRange();
@@ -3164,7 +3190,9 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
!Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||
!Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc()) ||
!Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc()) ||
- !Diags.isIgnored(diag::warn_uninit_const_pointer, D->getBeginLoc())) {
+ !Diags.isIgnored(diag::warn_uninit_const_pointer, D->getBeginLoc()) ||
+ !Diags.isIgnored(diag::warn_erroneous_behavior_uninitialized_read,
+ D->getBeginLoc())) {
if (CFG *cfg = AC.getCFG()) {
UninitValsDiagReporter reporter(S);
UninitVariablesAnalysisStats stats;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ae779d6830d9b..6692d1d00a129 ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/177614
More information about the cfe-commits
mailing list