[clang] cde1df4 - Correct -Winfinite-recursion warning on potentially-unevaluated operand

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 30 06:09:42 PDT 2022


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;
+}


        


More information about the cfe-commits mailing list