Extract mark-no-return-function code into a function.
llvm-svn: 80979
This commit is contained in:
		
							parent
							
								
									1eaa90b901
								
							
						
					
					
						commit
						1748d8a43d
					
				| 
						 | 
					@ -1417,6 +1417,88 @@ static bool EvalOSAtomic(ExplodedNodeSet& Dst,
 | 
				
			||||||
//===----------------------------------------------------------------------===//
 | 
					//===----------------------------------------------------------------------===//
 | 
				
			||||||
// Transfer function: Function calls.
 | 
					// Transfer function: Function calls.
 | 
				
			||||||
//===----------------------------------------------------------------------===//
 | 
					//===----------------------------------------------------------------------===//
 | 
				
			||||||
 | 
					static void MarkNoReturnFunction(const FunctionDecl *FD, CallExpr *CE,
 | 
				
			||||||
 | 
					                                 const GRState *state, 
 | 
				
			||||||
 | 
					                                 GRStmtNodeBuilder *Builder) {
 | 
				
			||||||
 | 
					  if (FD->getAttr<NoReturnAttr>() || 
 | 
				
			||||||
 | 
					      FD->getAttr<AnalyzerNoReturnAttr>())
 | 
				
			||||||
 | 
					    Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    // HACK: Some functions are not marked noreturn, and don't return.
 | 
				
			||||||
 | 
					    //  Here are a few hardwired ones.  If this takes too long, we can
 | 
				
			||||||
 | 
					    //  potentially cache these results.
 | 
				
			||||||
 | 
					    const char* s = FD->getIdentifier()->getName();
 | 
				
			||||||
 | 
					    unsigned n = strlen(s);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    switch (n) {
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					    case 4:
 | 
				
			||||||
 | 
					      if (!memcmp(s, "exit", 4)) Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 5:
 | 
				
			||||||
 | 
					      if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					      else if (!memcmp(s, "error", 5)) {
 | 
				
			||||||
 | 
					        if (CE->getNumArgs() > 0) {
 | 
				
			||||||
 | 
					          SVal X = state->getSVal(*CE->arg_begin());
 | 
				
			||||||
 | 
					          // FIXME: use Assume to inspect the possible symbolic value of
 | 
				
			||||||
 | 
					          // X. Also check the specific signature of error().
 | 
				
			||||||
 | 
					          nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X);
 | 
				
			||||||
 | 
					          if (CI && CI->getValue() != 0)
 | 
				
			||||||
 | 
					            Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 6:
 | 
				
			||||||
 | 
					      if (!memcmp(s, "Assert", 6)) {
 | 
				
			||||||
 | 
					        Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					      // FIXME: This is just a wrapper around throwing an exception.
 | 
				
			||||||
 | 
					      //  Eventually inter-procedural analysis should handle this easily.
 | 
				
			||||||
 | 
					      if (!memcmp(s, "ziperr", 6)) Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					    case 7:
 | 
				
			||||||
 | 
					      if (!memcmp(s, "assfail", 7)) Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					    case 8:
 | 
				
			||||||
 | 
					      if (!memcmp(s ,"db_error", 8) || 
 | 
				
			||||||
 | 
					          !memcmp(s, "__assert", 8))
 | 
				
			||||||
 | 
					        Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					    case 12:
 | 
				
			||||||
 | 
					      if (!memcmp(s, "__assert_rtn", 12)) Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					    case 13:
 | 
				
			||||||
 | 
					      if (!memcmp(s, "__assert_fail", 13)) Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					    case 14:
 | 
				
			||||||
 | 
					      if (!memcmp(s, "dtrace_assfail", 14) ||
 | 
				
			||||||
 | 
					          !memcmp(s, "yy_fatal_error", 14))
 | 
				
			||||||
 | 
					        Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					    case 26:
 | 
				
			||||||
 | 
					      if (!memcmp(s, "_XCAssertionFailureHandler", 26) ||
 | 
				
			||||||
 | 
					          !memcmp(s, "_DTAssertionFailureHandler", 26) ||
 | 
				
			||||||
 | 
					          !memcmp(s, "_TSAssertionFailureHandler", 26))
 | 
				
			||||||
 | 
					        Builder->BuildSinks = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void GRExprEngine::EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L, 
 | 
					void GRExprEngine::EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L, 
 | 
				
			||||||
                            ExplodedNode* Pred) {
 | 
					                            ExplodedNode* Pred) {
 | 
				
			||||||
| 
						 | 
					@ -1498,86 +1580,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
 | 
					    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
 | 
				
			||||||
    const FunctionDecl* FD = L.getAsFunctionDecl();
 | 
					    const FunctionDecl* FD = L.getAsFunctionDecl();
 | 
				
			||||||
    if (FD) {      
 | 
					    if (FD)
 | 
				
			||||||
      if (FD->getAttr<NoReturnAttr>() || 
 | 
					      MarkNoReturnFunction(FD, CE, state, Builder);
 | 
				
			||||||
          FD->getAttr<AnalyzerNoReturnAttr>())
 | 
					 | 
				
			||||||
        Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
      else {
 | 
					 | 
				
			||||||
        // HACK: Some functions are not marked noreturn, and don't return.
 | 
					 | 
				
			||||||
        //  Here are a few hardwired ones.  If this takes too long, we can
 | 
					 | 
				
			||||||
        //  potentially cache these results.
 | 
					 | 
				
			||||||
        const char* s = FD->getIdentifier()->getName();
 | 
					 | 
				
			||||||
        unsigned n = strlen(s);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        switch (n) {
 | 
					 | 
				
			||||||
          default:
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
          case 4:
 | 
					 | 
				
			||||||
            if (!memcmp(s, "exit", 4)) Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          case 5:
 | 
					 | 
				
			||||||
            if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
            else if (!memcmp(s, "error", 5)) {
 | 
					 | 
				
			||||||
              if (CE->getNumArgs() > 0) {
 | 
					 | 
				
			||||||
                SVal X = state->getSVal(*CE->arg_begin());
 | 
					 | 
				
			||||||
                // FIXME: use Assume to inspect the possible symbolic value of
 | 
					 | 
				
			||||||
                // X. Also check the specific signature of error().
 | 
					 | 
				
			||||||
                nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X);
 | 
					 | 
				
			||||||
                if (CI && CI->getValue() != 0)
 | 
					 | 
				
			||||||
                  Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          case 6:
 | 
					 | 
				
			||||||
            if (!memcmp(s, "Assert", 6)) {
 | 
					 | 
				
			||||||
              Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
              break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            // FIXME: This is just a wrapper around throwing an exception.
 | 
					 | 
				
			||||||
            //  Eventually inter-procedural analysis should handle this easily.
 | 
					 | 
				
			||||||
            if (!memcmp(s, "ziperr", 6)) Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
          
 | 
					 | 
				
			||||||
          case 7:
 | 
					 | 
				
			||||||
            if (!memcmp(s, "assfail", 7)) Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
          case 8:
 | 
					 | 
				
			||||||
            if (!memcmp(s ,"db_error", 8) || 
 | 
					 | 
				
			||||||
                !memcmp(s, "__assert", 8))
 | 
					 | 
				
			||||||
              Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
          
 | 
					 | 
				
			||||||
          case 12:
 | 
					 | 
				
			||||||
            if (!memcmp(s, "__assert_rtn", 12)) Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
          case 13:
 | 
					 | 
				
			||||||
            if (!memcmp(s, "__assert_fail", 13)) Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
          case 14:
 | 
					 | 
				
			||||||
            if (!memcmp(s, "dtrace_assfail", 14) ||
 | 
					 | 
				
			||||||
                !memcmp(s, "yy_fatal_error", 14))
 | 
					 | 
				
			||||||
              Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
          case 26:
 | 
					 | 
				
			||||||
            if (!memcmp(s, "_XCAssertionFailureHandler", 26) ||
 | 
					 | 
				
			||||||
                !memcmp(s, "_DTAssertionFailureHandler", 26) ||
 | 
					 | 
				
			||||||
                !memcmp(s, "_TSAssertionFailureHandler", 26))
 | 
					 | 
				
			||||||
              Builder->BuildSinks = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Evaluate the call.
 | 
					    // Evaluate the call.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue