Author: Prathit Aswar Date: 2022-06-30T09:09:28-04:00 New Revision: cde1df4ca4f233f1069041ed1646779e9ff1ad7d
URL: https://github.com/llvm/llvm-project/commit/cde1df4ca4f233f1069041ed1646779e9ff1ad7d DIFF: https://github.com/llvm/llvm-project/commit/cde1df4ca4f233f1069041ed1646779e9ff1ad7d.diff LOG: Correct -Winfinite-recursion warning on potentially-unevaluated operand Fixing issue "incorrect -Winfinite-recursion warning on potentially- unevaluated operand". We add a dedicated visit function (VisitCXXTypeidExpr) for typeid, instead of using the default (VisitStmt). In this new function we skip over building the CFG for unevaluated operands of typeid. Fixes #21668 Differential Revision: https://reviews.llvm.org/D128747 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Analysis/CFG.cpp clang/test/SemaCXX/warn-infinite-recursion.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b80e401e02f6c..e6353de934153 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -275,6 +275,10 @@ Improvements to Clang's diagnostics This fixes `Issue 55962 <https://github.com/llvm/llvm-project/issues/55962>`_. - Printable Unicode characters within `static_assert` messages are no longer escaped. +- The ``-Winfinite-recursion`` diagnostic no longer warns about + unevaluated operands of a ``typeid`` expression, as they are now + modeled correctly in the CFG. This fixes + `Issue 21668 <https://github.com/llvm/llvm-project/issues/21668>`_. Non-comprehensive list of changes in this release ------------------------------------------------- diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index b16898d3ffa0b..614d94ae31a6d 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -564,6 +564,7 @@ class CFGBuilder { 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 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc, 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,25 @@ CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) { 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 the block to avoid + // CFG generation for unevaluated operands. + if (S && !S->isTypeDependent() && S->isPotentiallyEvaluated()) + return VisitChildren(S); + + // Return block without CFG for unevaluated operands. + return Block; +} + CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) { CFGBlock *LoopSuccessor = nullptr; diff --git a/clang/test/SemaCXX/warn-infinite-recursion.cpp b/clang/test/SemaCXX/warn-infinite-recursion.cpp index e5a5a18b65717..8e07d5c876612 100644 --- a/clang/test/SemaCXX/warn-infinite-recursion.cpp +++ b/clang/test/SemaCXX/warn-infinite-recursion.cpp @@ -171,3 +171,35 @@ int test_wrapper() { } int wrapper_sum = test_wrapper<2>(); // expected-note{{instantiation}} + +namespace std { +class type_info { +public: + virtual ~type_info(); + const char *name() const { return __name; } + bool operator==(const type_info &__arg) const { + return __name == __arg.__name; + } + + bool operator!=(const type_info &__arg) const { + return !operator==(__arg); + } + +protected: + const char *__name; +}; +} // namespace std +struct Q { + virtual ~Q() = default; +}; + +Q q; +Q &evaluated_recursive_function(int x) { // expected-warning{{call itself}} + (void)typeid(evaluated_recursive_function(x)); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}} + return q; +} + +int unevaluated_recursive_function() { + (void)typeid(unevaluated_recursive_function()); + return 0; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits