Fix misspelling of function.

http://llvm-reviews.chandlerc.com/D1864

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1864?vs=4900&id=5147#toc

Files:
  test/Analysis/inlining/test-always-inline-size-option.c
  test/Analysis/misc-ps-region-store.cpp
  test/Analysis/cxx11-crashes.cpp
  test/Sema/warn-unused-function.c
  test/Sema/unused-expr-system-header.c
  test/Sema/attr-deprecated.c
  test/Parser/cxx-using-declaration.cpp
  test/Parser/expressions.c
  test/FixIt/fixit.c
  test/FixIt/typo.m
  test/CodeGen/functions.c
  test/SemaCXX/warn-bool-conversion.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/statements.cpp
  test/SemaCXX/warn-infinite-recursion.cpp
  test/Lexer/gnu-flags.c
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/AnalysisBasedWarnings.cpp
  lib/Lex/Pragma.cpp
Index: test/Analysis/inlining/test-always-inline-size-option.c
===================================================================
--- test/Analysis/inlining/test-always-inline-size-option.c
+++ test/Analysis/inlining/test-always-inline-size-option.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-inline-max-stack-depth=3 -analyzer-config ipa-always-inline-size=3 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-inline-max-stack-depth=3 -analyzer-config ipa-always-inline-size=3 -Wno-infinite-recursion -verify %s
 
 void clang_analyzer_eval(int);
 int nested5() {
Index: test/Analysis/misc-ps-region-store.cpp
===================================================================
--- test/Analysis/misc-ps-region-store.cpp
+++ test/Analysis/misc-ps-region-store.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions
-// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions -Wno-infinite-recursion
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions -Wno-infinite-recursion
 
 void clang_analyzer_warnIfReached();
 
Index: test/Analysis/cxx11-crashes.cpp
===================================================================
--- test/Analysis/cxx11-crashes.cpp
+++ test/Analysis/cxx11-crashes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -std=c++11 -verify -Wno-infinite-recursion %s
 // expected-no-diagnostics
 
 // radar://11485149, PR12871
Index: test/Sema/warn-unused-function.c
===================================================================
--- test/Sema/warn-unused-function.c
+++ test/Sema/warn-unused-function.c
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -Wused-but-marked-unused -Wunused-function -Wunneeded-internal-declaration -verify %s
-// RUN: %clang_cc1 -fsyntax-only -verify -Wunused %s
-// RUN: %clang_cc1 -fsyntax-only -verify -Wall %s
+// RUN: %clang_cc1 -fsyntax-only -Wused-but-marked-unused -Wunused-function -Wunneeded-internal-declaration -Wno-infinite-recursion -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-infinite-recursion -verify -Wunused %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-infinite-recursion -verify -Wall %s
 
 void foo() {}
 static void f2() {} 
Index: test/Sema/unused-expr-system-header.c
===================================================================
--- test/Sema/unused-expr-system-header.c
+++ test/Sema/unused-expr-system-header.c
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -verify %s
 #include <unused-expr-system-header.h>
-void f(int i1, int i2) {
+void f(int i1, int i2);
+void g(int i1, int i2) {
   POSSIBLY_BAD_MACRO(5);
   STATEMENT_EXPR_MACRO(5);
   COMMA_MACRO_1(i1 == i2, f(i1, i2)); // expected-warning {{comparison result unused}} \
Index: test/Sema/attr-deprecated.c
===================================================================
--- test/Sema/attr-deprecated.c
+++ test/Sema/attr-deprecated.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only
+// RUN: %clang_cc1 %s -Wno-infinite-recursion -verify -fsyntax-only
 
 int f() __attribute__((deprecated)); // expected-note 2 {{declared here}}
 void g() __attribute__((deprecated));
Index: test/Parser/cxx-using-declaration.cpp
===================================================================
--- test/Parser/cxx-using-declaration.cpp
+++ test/Parser/cxx-using-declaration.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-infinite-recursion -verify %s
 
 namespace A {
     int VA;
Index: test/Parser/expressions.c
===================================================================
--- test/Parser/expressions.c
+++ test/Parser/expressions.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-infinite-recursion -verify %s
 
 void test1() {
   if (sizeof (int){ 1}) {}   // sizeof compound literal
Index: test/FixIt/fixit.c
===================================================================
--- test/FixIt/fixit.c
+++ test/FixIt/fixit.c
@@ -65,7 +65,6 @@
 
 void removeUnusedLabels(char c) {
   L0 /*removed comment*/:        c++; // expected-warning {{unused label}}
-  removeUnusedLabels(c);
   L1: // expected-warning {{unused label}}
   c++;
   /*preserved comment*/ L2  :        c++; // expected-warning {{unused label}}
Index: test/FixIt/typo.m
===================================================================
--- test/FixIt/typo.m
+++ test/FixIt/typo.m
@@ -147,7 +147,8 @@
 @end
 #endif
 
-void f(A *a) {
+void f(A *a);
+void test_f(A *a) {
   f(a) // expected-error{{expected ';' after expression}}
   [a methodA] // expected-error{{expected ';' after expression}}
   [A methodA] // expected-error{{expected ';' after expression}}
Index: test/CodeGen/functions.c
===================================================================
--- test/CodeGen/functions.c
+++ test/CodeGen/functions.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple i386-unknown-unknown -emit-llvm -o - -verify | FileCheck %s
+// RUN: %clang_cc1 %s -Wno-infinite-recursion -triple i386-unknown-unknown -emit-llvm -o - -verify | FileCheck %s
 
 int g();
 
Index: test/SemaCXX/warn-bool-conversion.cpp
===================================================================
--- test/SemaCXX/warn-bool-conversion.cpp
+++ test/SemaCXX/warn-bool-conversion.cpp
@@ -2,7 +2,8 @@
 
 int* j = false; // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}}
 
-void foo(int* i, int *j=(false)) // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}}
+void foo(int* i, int *j=(false)); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}}
+void bar()
 {
   foo(false); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}}
   foo((int*)false); // no-warning: explicit cast
Index: test/SemaCXX/MicrosoftCompatibility.cpp
===================================================================
--- test/SemaCXX/MicrosoftCompatibility.cpp
+++ test/SemaCXX/MicrosoftCompatibility.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -Wno-infinite-recursion -verify -fms-compatibility -fexceptions -fcxx-exceptions
 
 
 typedef unsigned short char16_t;
Index: test/SemaCXX/statements.cpp
===================================================================
--- test/SemaCXX/statements.cpp
+++ test/SemaCXX/statements.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fsyntax-only -pedantic -verify
+// RUN: %clang_cc1 %s -fsyntax-only -Wno-infinite-recursion -pedantic -verify
 
 void foo() { 
   return foo();
Index: test/SemaCXX/warn-infinite-recursion.cpp
===================================================================
--- test/SemaCXX/warn-infinite-recursion.cpp
+++ test/SemaCXX/warn-infinite-recursion.cpp
@@ -0,0 +1,122 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+
+void a() {  // expected-warning{{call itself}}
+  a();
+}
+
+void b(int x) {  // expected-warning{{call itself}}
+  if (x)
+    b(x);
+  else
+    b(x+1);
+}
+
+void c(int x) {
+  if (x)
+    c(5);
+}
+
+void d(int x) {  // expected-warning{{call itself}}
+  if (x)
+    ++x;
+  return d(x);
+}
+
+// Doesn't warn on mutually recursive functions
+void e();
+void f();
+
+void e() { f(); }
+void f() { e(); }
+
+// Don't warn on infinite loops
+void g() {
+  while (true)
+    g();
+
+  g();
+}
+
+void h(int x) {
+  while (x < 5) {
+    h(x+1);
+  }
+}
+
+void i(int x) {  // expected-warning{{call itself}}
+  while (x < 5) {
+    --x;
+  }
+  i(0);
+}
+
+int j() {  // expected-warning{{call itself}}
+  return 5 + j();
+}
+
+class S {
+  static void a();
+  void b();
+};
+
+void S::a() {  // expected-warning{{call itself}}
+  return a();
+}
+
+void S::b() {  // expected-warning{{call itself}}
+  int i = 0;
+  do {
+    ++i;
+    b();
+  } while (i > 5);
+}
+
+template<class member>
+struct T {
+  member m;
+  void a() { return a(); }  // expected-warning{{call itself}}
+  static void b() { return b(); }  // expected-warning{{call itself}}
+};
+
+void test_T() {
+  T<int> foo;
+  foo.a();  // expected-note{{in instantiation}}
+  foo.b();  // expected-note{{in instantiation}}
+}
+
+// No warnings on templated functions
+// sum<0>() is instantiated, does recursively call itself, but never runs.
+template <int value>
+int sum() {
+  return value + sum<value/2>();
+}
+
+template<>
+int sum<1>() { return 1; }
+
+template<int x, int y>
+int calculate_value() {
+  if (x != y)
+    return sum<x - y>();  // This instantiates sum<0>() even if never called.
+  else
+    return 0;
+}
+
+int value = calculate_value<1,1>();
+
+void DoSomethingHere();
+
+// DoStuff<0,0>() is instantiated, but never called.
+template<int First, int Last>
+int DoStuff() {
+  if (First + 1 == Last) {
+    // This branch gets removed during <0, 0> instantiation in so CFG for this
+    // function goes straight to the else branch.
+    DoSomethingHere();
+  } else {
+    DoStuff<First, (First + Last)/2>();
+    DoStuff<(First + Last)/2, Last>();
+  }
+  return 0;
+}
+int stuff = DoStuff<0, 1>();
Index: test/Lexer/gnu-flags.c
===================================================================
--- test/Lexer/gnu-flags.c
+++ test/Lexer/gnu-flags.c
@@ -18,14 +18,15 @@
 
 
 #if ALL || ZEROARGS
-// expected-warning@+9 {{must specify at least one argument for '...' parameter of variadic macro}}
+// expected-warning@+10 {{must specify at least one argument for '...' parameter of variadic macro}}
 // expected-note@+4 {{macro 'efoo' defined here}}
 // expected-warning@+3 {{token pasting of ',' and __VA_ARGS__ is a GNU extension}}
 #endif
 
 #define efoo(format, args...) foo(format , ##args)
 
-void foo( const char* c )
+void foo( const char* c );
+void foo_test()
 {
   efoo("6");
 }
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -161,6 +161,7 @@
 def DanglingElse: DiagGroup<"dangling-else">;
 def DanglingField : DiagGroup<"dangling-field">;
 def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
+def InfiniteRecursion : DiagGroup<"infinite-recursion">;
 def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">;
 def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
 def : DiagGroup<"import">;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -30,6 +30,10 @@
   "been assigned">, InGroup<DiagGroup<"duplicate-enum">>, DefaultIgnore;
 def note_duplicate_element : Note<"element %0 also has value %1">;
 
+def warn_infinite_recursive_function : Warning<
+  "all paths through this function will call itself">,
+  InGroup<InfiniteRecursion>;
+
 // Constant expressions
 def err_expr_not_ice : Error<
   "expression is not an %select{integer|integral}0 constant expression">;
Index: lib/Sema/AnalysisBasedWarnings.cpp
===================================================================
--- lib/Sema/AnalysisBasedWarnings.cpp
+++ lib/Sema/AnalysisBasedWarnings.cpp
@@ -78,6 +78,74 @@
 }
 
 //===----------------------------------------------------------------------===//
+// Check for infinite self-recursion in functions
+//===----------------------------------------------------------------------===//
+
+enum RecursiveState {
+  Unknown,
+  AfterFunctionCall,
+  Reachable
+};
+
+static void CheckForFunctionCall(Sema &S, const FunctionDecl *FD,
+                                 CFGBlock& Block, unsigned exitID,
+                                 llvm::SmallVectorImpl<RecursiveState> &states,
+                                 RecursiveState state) {
+  unsigned ID = Block.getBlockID();
+
+  if (states[ID] < state)
+    states[ID] = state;
+  else
+    return;
+
+  if (state == Reachable) {
+    for (CFGBlock::iterator I = Block.begin(), E = Block.end(); I != E; ++I) {
+      if (I->getKind() != CFGElement::Statement)
+        continue;
+
+      const CallExpr *CE = dyn_cast<CallExpr>(I->getAs<CFGStmt>()->getStmt());
+      if (CE && CE->getCalleeDecl() == FD) {
+        if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) {
+          if (isa<CXXThisExpr>(MCE->getImplicitObjectArgument())) {
+            state = AfterFunctionCall;
+            break;
+          }
+        } else {
+          state = AfterFunctionCall;
+          break;
+        }
+      }
+    }
+  }
+
+  for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end();
+       I != E; ++I)
+    if (*I)
+      CheckForFunctionCall(S, FD, **I, exitID, states, state);
+}
+
+static void CheckRecursiveFunction(Sema &S, const FunctionDecl *FD,
+                                   const Stmt *Body,
+                                   AnalysisDeclContext &AC) {
+  // Only run on non-templated functions and non-templated members of
+  // templated classes.
+  if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate &&
+      FD->getTemplatedKind() != FunctionDecl::TK_MemberSpecialization)
+    return;
+
+  CFG *cfg = AC.getCFG();
+  if (cfg == 0) return;
+  llvm::SmallVector<RecursiveState, 16> states(cfg->getNumBlockIDs(), Unknown);
+  CheckForFunctionCall(S, FD, cfg->getEntry(), cfg->getExit().getBlockID(),
+                       states, Reachable);
+
+  // Check that the exit block is reachable.  This prevents triggering the
+  // warning on 
+  if (states[cfg->getExit().getBlockID()] == AfterFunctionCall)
+    S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
+}
+
+//===----------------------------------------------------------------------===//
 // Check for missing return value.
 //===----------------------------------------------------------------------===//
 
@@ -1770,6 +1838,16 @@
                                D->getLocStart()) != DiagnosticsEngine::Ignored)
     diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
 
+
+  // Check for infinite self-recursion in functions
+  if (Diags.getDiagnosticLevel(diag::warn_infinite_recursive_function,
+                               D->getLocStart())
+      != DiagnosticsEngine::Ignored) {
+    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+      CheckRecursiveFunction(S, FD, Body, AC);
+    }
+  }
+
   // Collect statistics about the CFG if it was built.
   if (S.CollectStats && AC.isCFGBuilt()) {
     ++NumFunctionsAnalyzed;
Index: lib/Lex/Pragma.cpp
===================================================================
--- lib/Lex/Pragma.cpp
+++ lib/Lex/Pragma.cpp
@@ -926,12 +926,20 @@
 #ifdef _MSC_VER
     #pragma warning(disable : 4717)
 #endif
+// Disable Clang's warning about infinite recursion.
+#ifdef __clang__
+    #pragma clang diagnostic push
+    #pragma clang diagnostic ignored "-Winfinite-recursion"
+#endif
   void DebugOverflowStack() {
     DebugOverflowStack();
   }
 #ifdef _MSC_VER
     #pragma warning(default : 4717)
 #endif
+#ifdef __clang__
+    #pragma clang diagnostic pop
+#endif
 
 };
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to