rnk created this revision. rnk added reviewers: niravd, rsmith, nickdesaulniers.
There aren't any lifetime issues inherent in returning a local label. Hypothetically, it could be used to drive a state machine driven by computed goto the next time that same scope is re-entered. In any case, the Linux kernel uses this code pattern to get PCs, and we don't want to warn on that code pattern. Fixes PR38569 https://reviews.llvm.org/D50805 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaInit.cpp clang/test/Analysis/stack-addr-ps.cpp clang/test/Sema/statements.c 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 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 <typename T> 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<AddrLabelExpr>(Init)), RK_ReferenceBinding); - break; - default: break; } @@ -6923,8 +6917,6 @@ << isa<ParmVarDecl>(DRE->getDecl()) << DiagRange; } else if (isa<BlockExpr>(L)) { Diag(DiagLoc, diag::err_ret_local_block) << DiagRange; - } else if (isa<AddrLabelExpr>(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/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<ReturnStackAddress>; -def warn_ret_addr_label : Warning< - "returning address of label, which is local">, - InGroup<ReturnStackAddress>; def err_ret_local_block : Error< "returning block that lives on the local stack">; def note_local_var_initializer : Note<
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 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 <typename T> 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<AddrLabelExpr>(Init)), RK_ReferenceBinding); - break; - default: break; } @@ -6923,8 +6917,6 @@ << isa<ParmVarDecl>(DRE->getDecl()) << DiagRange; } else if (isa<BlockExpr>(L)) { Diag(DiagLoc, diag::err_ret_local_block) << DiagRange; - } else if (isa<AddrLabelExpr>(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/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<ReturnStackAddress>; -def warn_ret_addr_label : Warning< - "returning address of label, which is local">, - InGroup<ReturnStackAddress>; def err_ret_local_block : Error< "returning block that lives on the local stack">; def note_local_var_initializer : Note<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits