appmonster007 created this revision. appmonster007 added a reviewer: aaron.ballman. appmonster007 added a project: clang. Herald added a project: All. appmonster007 requested review of this revision. Herald added a subscriber: cfe-commits.
Fixing issue "incorrect -Winfinite-recursion warning on potentially-unevaluated operand #21668” By having dedicated visit function (`VisitCXXTypeidExpr`) for `typeid`, instead of using default (`VisitStmt`). In this new function we skip over CFG build for unevaluated operands of `typeid` Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D128747 Files: clang/lib/Analysis/CFG.cpp clang/test/SemaCXX/warn-infinite-recursion.cpp Index: clang/test/SemaCXX/warn-infinite-recursion.cpp =================================================================== --- clang/test/SemaCXX/warn-infinite-recursion.cpp +++ clang/test/SemaCXX/warn-infinite-recursion.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -Winfinite-recursion +#include <typeinfo> + void a() { // expected-warning{{call itself}} a(); } @@ -171,3 +173,18 @@ } int wrapper_sum = test_wrapper<2>(); // expected-note{{instantiation}} + +struct Q { + virtual ~Q(){}; +}; + +Q q; +Q &evaluated_recursive_function(int x) { + typeid(evaluated_recursive_function(x)); + return q; +} + +int unevaluated_recursive_function() { + typeid(unevaluated_recursive_function()); + return 0; +} \ No newline at end of file Index: clang/lib/Analysis/CFG.cpp =================================================================== --- clang/lib/Analysis/CFG.cpp +++ clang/lib/Analysis/CFG.cpp @@ -564,6 +564,7 @@ AddStmtChoice asc); CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); + CFGBlock *VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc); CFGBlock *VisitDeclStmt(DeclStmt *DS); CFGBlock *VisitDeclSubExpr(DeclStmt *DS); CFGBlock *VisitDefaultStmt(DefaultStmt *D); @@ -2220,6 +2221,9 @@ case Stmt::CXXTryStmtClass: return VisitCXXTryStmt(cast<CXXTryStmt>(S)); + case Stmt::CXXTypeidExprClass: + return VisitCXXTypeidExpr(cast<CXXTypeidExpr>(S), asc); + case Stmt::CXXForRangeStmtClass: return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S)); @@ -4045,6 +4049,28 @@ return VisitStmt(T, AddStmtChoice::AlwaysAdd); } +CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) { + if (asc.alwaysAdd(*this, S)) { + autoCreateBlock(); + appendStmt(Block, S); + } + + // C++ [expr.typeid]p3: + // When typeid is applied to an expression other than an glvalue of a + // polymorphic class type [...] [the] expression is an unevaluated + // operand. [...] + // We add only potentially evaluated statements to block to avoid + // CFG generation for unevaluated operands. + if (S && !S->isTypeDependent()) { + if (S->isPotentiallyEvaluated()) { + return VisitChildren(S); + } + } + + // Return block without CFG for unevaluated operands. + return Block; +} + CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) { CFGBlock *LoopSuccessor = nullptr;
Index: clang/test/SemaCXX/warn-infinite-recursion.cpp =================================================================== --- clang/test/SemaCXX/warn-infinite-recursion.cpp +++ clang/test/SemaCXX/warn-infinite-recursion.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -Winfinite-recursion +#include <typeinfo> + void a() { // expected-warning{{call itself}} a(); } @@ -171,3 +173,18 @@ } int wrapper_sum = test_wrapper<2>(); // expected-note{{instantiation}} + +struct Q { + virtual ~Q(){}; +}; + +Q q; +Q &evaluated_recursive_function(int x) { + typeid(evaluated_recursive_function(x)); + return q; +} + +int unevaluated_recursive_function() { + typeid(unevaluated_recursive_function()); + return 0; +} \ No newline at end of file Index: clang/lib/Analysis/CFG.cpp =================================================================== --- clang/lib/Analysis/CFG.cpp +++ clang/lib/Analysis/CFG.cpp @@ -564,6 +564,7 @@ AddStmtChoice asc); CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); + CFGBlock *VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc); CFGBlock *VisitDeclStmt(DeclStmt *DS); CFGBlock *VisitDeclSubExpr(DeclStmt *DS); CFGBlock *VisitDefaultStmt(DefaultStmt *D); @@ -2220,6 +2221,9 @@ case Stmt::CXXTryStmtClass: return VisitCXXTryStmt(cast<CXXTryStmt>(S)); + case Stmt::CXXTypeidExprClass: + return VisitCXXTypeidExpr(cast<CXXTypeidExpr>(S), asc); + case Stmt::CXXForRangeStmtClass: return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S)); @@ -4045,6 +4049,28 @@ return VisitStmt(T, AddStmtChoice::AlwaysAdd); } +CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) { + if (asc.alwaysAdd(*this, S)) { + autoCreateBlock(); + appendStmt(Block, S); + } + + // C++ [expr.typeid]p3: + // When typeid is applied to an expression other than an glvalue of a + // polymorphic class type [...] [the] expression is an unevaluated + // operand. [...] + // We add only potentially evaluated statements to block to avoid + // CFG generation for unevaluated operands. + if (S && !S->isTypeDependent()) { + if (S->isPotentiallyEvaluated()) { + return VisitChildren(S); + } + } + + // Return block without CFG for unevaluated operands. + return Block; +} + CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) { CFGBlock *LoopSuccessor = nullptr;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits