Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7869,9 +7869,6 @@ def warn_ret_local_temp_addr_ref : Warning< "returning %select{address of|reference to}0 local temporary object">, InGroup; -def warn_ret_addr_label : Warning< - "returning address of label, which is local">, - InGroup; def err_ret_local_block : Error< "returning block that lives on the local stack">; def note_local_var_initializer : Note< Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -6291,7 +6291,6 @@ /// A temporary or local variable. This will be one of: /// * A MaterializeTemporaryExpr. /// * A DeclRefExpr whose declaration is a local. -/// * An AddrLabelExpr. /// * A BlockExpr for a block with captures. using Local = Expr*; @@ -6735,11 +6734,6 @@ } break; - case Stmt::AddrLabelExprClass: - // We want to warn if the address of a label would escape the function. - Visit(Path, Local(cast(Init)), RK_ReferenceBinding); - break; - default: break; } @@ -6923,8 +6917,6 @@ << isa(DRE->getDecl()) << DiagRange; } else if (isa(L)) { Diag(DiagLoc, diag::err_ret_local_block) << DiagRange; - } else if (isa(L)) { - Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange; } else { Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref) << Entity.getType()->isReferenceType() << DiagRange; Index: clang/test/Analysis/stack-addr-ps.cpp =================================================================== --- clang/test/Analysis/stack-addr-ps.cpp +++ clang/test/Analysis/stack-addr-ps.cpp @@ -74,10 +74,12 @@ return &x; // expected-warning{{Address of stack memory associated with local variable 's1' returned}} expected-warning {{address of stack memory associated with local variable 's1' returned}} } +// PR38569: Clang used to warn when returning label addresses, but now it +// doesn't. void *lf() { label: - void *const &x = &&label; // expected-note {{binding reference variable 'x' here}} - return x; // expected-warning {{returning address of label, which is local}} + void *const &x = &&label; + return x; } template Index: clang/test/Sema/statements.c =================================================================== --- clang/test/Sema/statements.c +++ clang/test/Sema/statements.c @@ -29,9 +29,22 @@ } -void *test10() { +// PR38569: Clang used to warn on returning the address of a label, but we don't +// anymore. Labels aren't exactly destroyed when they go out of scope, and the +// Linux kernel uses this functionality. +void *test10() { bar: - return &&bar; // expected-warning {{returning address of label, which is local}} + return &&bar; +} + +// Linux actually does something more like this, and we don't want to warn on +// it. +void test10_logpc(void*); +void test10a() { + test10_logpc(({ + my_pc: + &&my_pc; + })); } // PR6034