Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -311,7 +311,7 @@ def InvalidNoreturn : DiagGroup<"invalid-noreturn">; def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">; def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">; -def : DiagGroup<"init-self">; +def InitSelf : DiagGroup<"init-self">; def : DiagGroup<"inline">; def : DiagGroup<"invalid-pch">; def GNULabelsAsValue : DiagGroup<"gnu-label-as-value">; @@ -775,6 +775,7 @@ Format, Implicit, InfiniteRecursion, + InitSelf, MismatchedTags, MissingBraces, Move, Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -1907,6 +1907,8 @@ def warn_uninit_self_reference_in_init : Warning< "variable %0 is uninitialized when used within its own initialization">, InGroup; +def warn_uninit_self_init : Warning<"variable %0 is initialized with itself">, + InGroup, DefaultIgnore; def warn_uninit_self_reference_in_reference_init : Warning< "reference %0 is not yet bound to a value when used within its own" " initialization">, Index: lib/Sema/AnalysisBasedWarnings.cpp =================================================================== --- lib/Sema/AnalysisBasedWarnings.cpp +++ lib/Sema/AnalysisBasedWarnings.cpp @@ -977,7 +977,8 @@ // uninitialized. Proven code paths which access 'x' in // an uninitialized state after this will still warn. if (const Expr *Initializer = VD->getInit()) { - if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts()) + if (!VD->getType().isConstQualified() && !alwaysReportSelfInit && + DRE == Initializer->IgnoreParenImpCasts()) return false; ContainsReference CR(S.Context, DRE); @@ -1518,10 +1519,17 @@ UsesVec *vec = V.getPointer(); bool hasSelfInit = V.getInt(); - // Specially handle the case where we have uses of an uninitialized - // variable, but the root cause is an idiomatic self-init. We want - // to report the diagnostic at the self-init since that is the root cause. - if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec)) + if (hasSelfInit && vd->getType().isConstQualified()) { + // Handle "const int a = a;" + DiagnoseUninitializedUse(S, vd, + UninitUse(vd->getInit()->IgnoreParenCasts(), + /* isAlwaysUninit */ true), + /* alwaysReportSelfInit */ true); + } else if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec)) + // Specially handle the case where we have uses of an uninitialized + // variable, but the root cause is an idiomatic self-init. We want + // to report the diagnostic at the self-init since that is the root + // cause. DiagnoseUninitializedUse(S, vd, UninitUse(vd->getInit()->IgnoreParenCasts(), /* isAlwaysUninit */ true), Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -11111,6 +11111,19 @@ Init = Result.getAs(); } + if (!VDecl->getType().isConstQualified()) { + if (auto *SubExpr = dyn_cast(Init->IgnoreParens())) { + if (SubExpr->getCastKind() == CK_LValueToRValue) { + if (auto *DRE = dyn_cast(SubExpr->getSubExpr())) { + if (DRE->getDecl() == VDecl) { + Diag(VDecl->getLocation(), diag::warn_uninit_self_init) + << VDecl << VDecl->getSourceRange() << DRE->getSourceRange(); + } + } + } + } + } + // Check for self-references within variable initializers. // Variables declared within a function/method body (except for references) // are handled by a dataflow analysis. Index: test/SemaCXX/uninitialized.cpp =================================================================== --- test/SemaCXX/uninitialized.cpp +++ test/SemaCXX/uninitialized.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value -Wno-unused-lambda-capture -std=c++1z -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -Wno-unused -std=c++1z -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wall -Wno-unused -Wno-init-self -std=c++1z -verify %s // definitions for std::move namespace std { @@ -1432,7 +1433,7 @@ void array_capture(bool b) { const char fname[] = "array_capture"; if (b) { - int unused; // expected-warning {{unused variable}} + int unused; } else { [fname]{}; } @@ -1447,3 +1448,15 @@ switch (int n; (n == k || k > 5)) {} // expected-warning {{uninitialized}} expected-note {{initialize}} expected-warning {{boolean}} } + +namespace const_self_init { +const int a = a; // no-warning for global + +void const_init() { + const int a = a; // expected-warning {{variable 'a' is uninitialized when used within its own initialization}} + + const int b = b; // expected-warning {{variable 'b' is uninitialized when used within its own initialization}} + int c = b; +} + +}