]> granicus.if.org Git - clang/commitdiff
Further tweak -Wurneachable-code and templates by allowing the warning to run on
authorTed Kremenek <kremenek@apple.com>
Thu, 1 Dec 2011 00:59:17 +0000 (00:59 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 1 Dec 2011 00:59:17 +0000 (00:59 +0000)
explicit template specializations (which represent actual functions somebody wrote).

Along the way, refactor some other code which similarly cares about whether or
not they are looking at a template instantiation.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145547 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
lib/AST/Decl.cpp
lib/Sema/AnalysisBasedWarnings.cpp
lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
test/SemaCXX/warn-unreachable.cpp

index 2941982a2874dd1b45ca93130099724f1c3e4d16..b3b8da057de6f8b79c095d428962f179374d5d37 100644 (file)
@@ -1909,6 +1909,10 @@ public:
   /// be implicitly instantiated.
   bool isImplicitlyInstantiable() const;
 
+  /// \brief Determines if the given function was instantiated from a
+  /// function template.
+  bool isTemplateInstantiation() const;
+
   /// \brief Retrieve the function declaration from which this function could
   /// be instantiated, if it is an instantiation (rather than a non-template
   /// or a specialization, for example).
index 299ddd4b72112566506293a1c4b7f5b0a3ed60c0..7be4d26f9859af09adfeae9c3d15df8ae325b34f 100644 (file)
@@ -1951,7 +1951,20 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
     return true;
 
   return PatternDecl->isInlined();
-}                      
+}
+
+bool FunctionDecl::isTemplateInstantiation() const {
+  switch (getTemplateSpecializationKind()) {
+    case TSK_Undeclared:
+    case TSK_ExplicitSpecialization:
+      return false;      
+    case TSK_ImplicitInstantiation:
+    case TSK_ExplicitInstantiationDeclaration:
+    case TSK_ExplicitInstantiationDefinition:
+      return true;
+  }
+  llvm_unreachable("All TSK values handled.");
+}
    
 FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
   // Handle class scope explicit specialization special case.
index 54a26b3253ab2082a923233665a21040264b391e..fc635fba2dd06b9ab67ee50ba6fbd3f8e4bc5805 100644 (file)
@@ -241,19 +241,8 @@ struct CheckFallThroughDiagnostics {
     
     // Don't suggest that template instantiations be marked "noreturn"
     bool isTemplateInstantiation = false;
-    if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) {
-      switch (Function->getTemplateSpecializationKind()) {
-      case TSK_Undeclared:
-      case TSK_ExplicitSpecialization:
-        break;
-        
-      case TSK_ImplicitInstantiation:
-      case TSK_ExplicitInstantiationDeclaration:
-      case TSK_ExplicitInstantiationDefinition:
-        isTemplateInstantiation = true;
-        break;
-      }
-    }
+    if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
+      isTemplateInstantiation = Function->isTemplateInstantiation();
         
     if (!isVirtualMethod && !isTemplateInstantiation)
       D.diag_NeverFallThroughOrReturn =
@@ -919,7 +908,10 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
     // Different template instantiations can effectively change the control-flow
     // and it is very difficult to prove that a snippet of code in a template
     // is unreachable for all instantiations.
-    if (S.ActiveTemplateInstantiations.empty())
+    bool isTemplateInstantiation = false;
+    if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
+      isTemplateInstantiation = Function->isTemplateInstantiation();
+    if (!isTemplateInstantiation)
       CheckUnreachable(S, AC);
   }
 
index 97cc44f0cbdbaecde8cb8607f15cdac485ebbcc1..2b550df2b93f0339b086f812c825de2a068fc9dc 100644 (file)
@@ -54,10 +54,11 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
                                               BugReporter &B,
                                               ExprEngine &Eng) const {
   CFGBlocksSet reachable, visited;
-
+  
   if (Eng.hasWorkRemaining())
     return;
 
+  const Decl *D = 0;
   CFG *C = 0;
   ParentMap *PM = 0;
   const LocationContext *LC = 0;
@@ -67,6 +68,8 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
     const ProgramPoint &P = I->getLocation();
     LC = P.getLocationContext();
 
+    if (!D)
+      D = LC->getAnalysisDeclContext()->getDecl();
     // Save the CFG if we don't have it already
     if (!C)
       C = LC->getAnalysisDeclContext()->getUnoptimizedCFG();
@@ -80,8 +83,15 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
   }
 
   // Bail out if we didn't get the CFG or the ParentMap.
-  if (!C || !PM)
+  if (!D || !C || !PM)
     return;
+  
+  // Don't do anything for template instantiations.  Proving that code
+  // in a template instantiation is unreachable means proving that it is
+  // unreachable in all instantiations.
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    if (FD->isTemplateInstantiation())
+      return;
 
   // Find CFGBlocks that were not covered by any node
   for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) {
index fa740bac65821dd5b45c1c7d1c61839b89611b3d..f36300af4d38322f5838d7e84fe1ff63ad63ada1 100644 (file)
@@ -98,3 +98,12 @@ void test_unreachable_templates_harness() {
   test_unreachable_templates<TestUnreachableB>(); 
 }
 
+// Do warn about explict template specializations, as they represent
+// actual concrete functions that somebody wrote.
+
+template <typename T> void funcToSpecialize() {}
+template <> void funcToSpecialize<int>() {
+  halt();
+  dead(); // expected-warning {{will never be executed}}
+}
+