195 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- AnalyzerOptions.cpp - Analysis Engine Options ----------------------===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file contains special accessors for analyzer configuration options
 | 
						|
// with string representations.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
 | 
						|
#include "clang/StaticAnalyzer/Core/Checker.h"
 | 
						|
#include "llvm/ADT/SmallString.h"
 | 
						|
#include "llvm/ADT/StringSwitch.h"
 | 
						|
#include "llvm/ADT/StringRef.h"
 | 
						|
#include "llvm/ADT/Twine.h"
 | 
						|
#include "llvm/Support/ErrorHandling.h"
 | 
						|
#include "llvm/Support/FileSystem.h"
 | 
						|
#include "llvm/Support/FormattedStream.h"
 | 
						|
#include "llvm/Support/raw_ostream.h"
 | 
						|
#include <cassert>
 | 
						|
#include <cstddef>
 | 
						|
#include <utility>
 | 
						|
#include <vector>
 | 
						|
 | 
						|
using namespace clang;
 | 
						|
using namespace ento;
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
void AnalyzerOptions::printFormattedEntry(
 | 
						|
    llvm::raw_ostream &Out,
 | 
						|
    std::pair<StringRef, StringRef> EntryDescPair,
 | 
						|
    size_t InitialPad, size_t EntryWidth, size_t MinLineWidth) {
 | 
						|
 | 
						|
  llvm::formatted_raw_ostream FOut(Out);
 | 
						|
 | 
						|
  const size_t PadForDesc = InitialPad + EntryWidth;
 | 
						|
 | 
						|
  FOut.PadToColumn(InitialPad) << EntryDescPair.first;
 | 
						|
  // If the buffer's length is greater then PadForDesc, print a newline.
 | 
						|
  if (FOut.getColumn() > PadForDesc)
 | 
						|
    FOut << '\n';
 | 
						|
 | 
						|
  FOut.PadToColumn(PadForDesc);
 | 
						|
 | 
						|
  if (MinLineWidth == 0) {
 | 
						|
    FOut << EntryDescPair.second;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (char C : EntryDescPair.second) {
 | 
						|
    if (FOut.getColumn() > MinLineWidth && C == ' ') {
 | 
						|
      FOut << '\n';
 | 
						|
      FOut.PadToColumn(PadForDesc);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    FOut << C;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
ExplorationStrategyKind
 | 
						|
AnalyzerOptions::getExplorationStrategy() const {
 | 
						|
  auto K =
 | 
						|
    llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
 | 
						|
                                                            ExplorationStrategy)
 | 
						|
          .Case("dfs", ExplorationStrategyKind::DFS)
 | 
						|
          .Case("bfs", ExplorationStrategyKind::BFS)
 | 
						|
          .Case("unexplored_first",
 | 
						|
                ExplorationStrategyKind::UnexploredFirst)
 | 
						|
          .Case("unexplored_first_queue",
 | 
						|
                ExplorationStrategyKind::UnexploredFirstQueue)
 | 
						|
          .Case("unexplored_first_location_queue",
 | 
						|
                ExplorationStrategyKind::UnexploredFirstLocationQueue)
 | 
						|
          .Case("bfs_block_dfs_contents",
 | 
						|
                ExplorationStrategyKind::BFSBlockDFSContents)
 | 
						|
          .Default(None);
 | 
						|
  assert(K.hasValue() && "User mode is invalid.");
 | 
						|
  return K.getValue();
 | 
						|
}
 | 
						|
 | 
						|
IPAKind AnalyzerOptions::getIPAMode() const {
 | 
						|
  auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode)
 | 
						|
          .Case("none", IPAK_None)
 | 
						|
          .Case("basic-inlining", IPAK_BasicInlining)
 | 
						|
          .Case("inlining", IPAK_Inlining)
 | 
						|
          .Case("dynamic", IPAK_DynamicDispatch)
 | 
						|
          .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
 | 
						|
          .Default(None);
 | 
						|
  assert(K.hasValue() && "IPA Mode is invalid.");
 | 
						|
 | 
						|
  return K.getValue();
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
AnalyzerOptions::mayInlineCXXMemberFunction(
 | 
						|
                                          CXXInlineableMemberKind Param) const {
 | 
						|
  if (getIPAMode() < IPAK_Inlining)
 | 
						|
    return false;
 | 
						|
 | 
						|
  auto K =
 | 
						|
    llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
 | 
						|
                                                          CXXMemberInliningMode)
 | 
						|
    .Case("constructors", CIMK_Constructors)
 | 
						|
    .Case("destructors", CIMK_Destructors)
 | 
						|
    .Case("methods", CIMK_MemberFunctions)
 | 
						|
    .Case("none", CIMK_None)
 | 
						|
    .Default(None);
 | 
						|
 | 
						|
  assert(K.hasValue() && "Invalid c++ member function inlining mode.");
 | 
						|
 | 
						|
  return *K >= Param;
 | 
						|
}
 | 
						|
 | 
						|
StringRef AnalyzerOptions::getCheckerStringOption(StringRef CheckerName,
 | 
						|
                                                  StringRef OptionName,
 | 
						|
                                                  bool SearchInParents) const {
 | 
						|
  assert(!CheckerName.empty() &&
 | 
						|
         "Empty checker name! Make sure the checker object (including it's "
 | 
						|
         "bases!) if fully initialized before calling this function!");
 | 
						|
 | 
						|
  ConfigTable::const_iterator E = Config.end();
 | 
						|
  do {
 | 
						|
    ConfigTable::const_iterator I =
 | 
						|
        Config.find((Twine(CheckerName) + ":" + OptionName).str());
 | 
						|
    if (I != E)
 | 
						|
      return StringRef(I->getValue());
 | 
						|
    size_t Pos = CheckerName.rfind('.');
 | 
						|
    if (Pos == StringRef::npos)
 | 
						|
      break;
 | 
						|
 | 
						|
    CheckerName = CheckerName.substr(0, Pos);
 | 
						|
  } while (!CheckerName.empty() && SearchInParents);
 | 
						|
 | 
						|
  assert(false && "Unknown checker option! Did you call getChecker*Option "
 | 
						|
                  "with incorrect parameters? User input must've been "
 | 
						|
                  "verified by CheckerRegistry.");
 | 
						|
 | 
						|
  return "";
 | 
						|
}
 | 
						|
 | 
						|
StringRef AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase *C,
 | 
						|
                                                  StringRef OptionName,
 | 
						|
                                                  bool SearchInParents) const {
 | 
						|
  return getCheckerStringOption(
 | 
						|
                           C->getTagDescription(), OptionName, SearchInParents);
 | 
						|
}
 | 
						|
 | 
						|
bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName,
 | 
						|
                                              StringRef OptionName,
 | 
						|
                                              bool SearchInParents) const {
 | 
						|
  auto Ret = llvm::StringSwitch<llvm::Optional<bool>>(
 | 
						|
      getCheckerStringOption(CheckerName, OptionName,
 | 
						|
                             SearchInParents))
 | 
						|
      .Case("true", true)
 | 
						|
      .Case("false", false)
 | 
						|
      .Default(None);
 | 
						|
 | 
						|
  assert(Ret &&
 | 
						|
         "This option should be either 'true' or 'false', and should've been "
 | 
						|
         "validated by CheckerRegistry!");
 | 
						|
 | 
						|
  return *Ret;
 | 
						|
}
 | 
						|
 | 
						|
bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase *C,
 | 
						|
                                              StringRef OptionName,
 | 
						|
                                              bool SearchInParents) const {
 | 
						|
  return getCheckerBooleanOption(
 | 
						|
             C->getTagDescription(), OptionName, SearchInParents);
 | 
						|
}
 | 
						|
 | 
						|
int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName,
 | 
						|
                                             StringRef OptionName,
 | 
						|
                                             bool SearchInParents) const {
 | 
						|
  int Ret = 0;
 | 
						|
  bool HasFailed = getCheckerStringOption(CheckerName, OptionName,
 | 
						|
                                          SearchInParents)
 | 
						|
                     .getAsInteger(0, Ret);
 | 
						|
  assert(!HasFailed &&
 | 
						|
         "This option should be numeric, and should've been validated by "
 | 
						|
         "CheckerRegistry!");
 | 
						|
  (void)HasFailed;
 | 
						|
  return Ret;
 | 
						|
}
 | 
						|
 | 
						|
int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase *C,
 | 
						|
                                             StringRef OptionName,
 | 
						|
                                             bool SearchInParents) const {
 | 
						|
  return getCheckerIntegerOption(
 | 
						|
                           C->getTagDescription(), OptionName, SearchInParents);
 | 
						|
}
 |