Exemple #1
0
bool Commit::canInsertAfterToken(SourceLocation loc, FileOffset &offs,
                                 SourceLocation &AfterLoc) {
  if (loc.isInvalid())

    return false;

  SourceLocation spellLoc = SourceMgr.getSpellingLoc(loc);
  unsigned tokLen = Lexer::MeasureTokenLength(spellLoc, SourceMgr, LangOpts);
  AfterLoc = loc.getLocWithOffset(tokLen);

  if (loc.isMacroID())
    isAtEndOfMacroExpansion(loc, &loc);

  const SourceManager &SM = SourceMgr;
  while (SM.isMacroArgExpansion(loc))
    loc = SM.getImmediateSpellingLoc(loc);

  if (loc.isMacroID())
    if (!isAtEndOfMacroExpansion(loc, &loc))
      return false;

  if (SM.isInSystemHeader(loc))
    return false;

  loc = Lexer::getLocForEndOfToken(loc, 0, SourceMgr, LangOpts);
  if (loc.isInvalid())
    return false;

  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
  if (locInfo.first.isInvalid())
    return false;
  offs = FileOffset(locInfo.first, locInfo.second);
  return canInsertInOffset(loc, offs);
}
void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *MatchedDecl = Result.Nodes.getNodeAs<TypedefDecl>("typedef");
  if (MatchedDecl->getLocation().isInvalid())
    return;

  auto &Context = *Result.Context;
  auto &SM = *Result.SourceManager;

  SourceLocation StartLoc = MatchedDecl->getBeginLoc();

  if (StartLoc.isMacroID() && IgnoreMacros)
    return;

  auto Diag =
      diag(StartLoc, "use 'using' instead of 'typedef'");

  // do not fix if there is macro or array
  if (MatchedDecl->getUnderlyingType()->isArrayType() || StartLoc.isMacroID())
    return;

  if (CheckRemoval(SM, StartLoc, Context)) {
    auto printPolicy = PrintingPolicy(getLangOpts());
    printPolicy.SuppressScope = true;
    printPolicy.ConstantArraySizeAsWritten = true;
    printPolicy.UseVoidForZeroParams = false;

    Diag << FixItHint::CreateReplacement(
        MatchedDecl->getSourceRange(),
        "using " + MatchedDecl->getNameAsString() + " = " +
            MatchedDecl->getUnderlyingType().getAsString(printPolicy));
  }
}
Exemple #3
0
static SourceLocation getTopMostMacro(SourceLocation Loc, SourceManager &SM) {
  assert(Loc.isMacroID());
  SourceLocation Last;
  while (Loc.isMacroID()) {
    Last = Loc;
    Loc = SM.getImmediateMacroCallerLoc(Loc);
  }
  return Last;
}
Exemple #4
0
/// \brief For a macro \arg Loc, returns the file spelling location and sets
/// to \arg isMacroArg whether the spelling resides inside a macro definition or
/// a macro argument.
static SourceLocation getFileSpellingLoc(SourceManager &SM,
                                         SourceLocation Loc,
                                         bool &isMacroArg) {
  assert(Loc.isMacroID());
  SourceLocation SpellLoc = SM.getImmediateSpellingLoc(Loc);
  if (SpellLoc.isMacroID())
    return getFileSpellingLoc(SM, SpellLoc, isMacroArg);
  
  isMacroArg = SM.isMacroArgExpansion(Loc);
  return SpellLoc;
}
/// Returns true if the statement is expanded from a configuration macro.
static bool isExpandedFromConfigurationMacro(const Stmt *S,
                                             Preprocessor &PP,
                                             bool IgnoreYES_NO = false) {
  // FIXME: This is not very precise.  Here we just check to see if the
  // value comes from a macro, but we can do much better.  This is likely
  // to be over conservative.  This logic is factored into a separate function
  // so that we can refine it later.
  SourceLocation L = S->getBeginLoc();
  if (L.isMacroID()) {
    SourceManager &SM = PP.getSourceManager();
    if (IgnoreYES_NO) {
      // The Objective-C constant 'YES' and 'NO'
      // are defined as macros.  Do not treat them
      // as configuration values.
      SourceLocation TopL = getTopMostMacro(L, SM);
      StringRef MacroName = PP.getImmediateMacroName(TopL);
      if (MacroName == "YES" || MacroName == "NO")
        return false;
    } else if (!PP.getLangOpts().CPlusPlus) {
      // Do not treat C 'false' and 'true' macros as configuration values.
      SourceLocation TopL = getTopMostMacro(L, SM);
      StringRef MacroName = PP.getImmediateMacroName(TopL);
      if (MacroName == "false" || MacroName == "true")
        return false;
    }
    return true;
  }
  return false;
}
Exemple #6
0
static PathDiagnosticCallPiece *
getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
                                const SourceManager &SMgr) {
  SourceLocation CallLoc = CP->callEnter.asLocation();

  // If the call is within a macro, don't do anything (for now).
  if (CallLoc.isMacroID())
    return 0;

  assert(SMgr.isFromMainFile(CallLoc) &&
         "The call piece should be in the main file.");

  // Check if CP represents a path through a function outside of the main file.
  if (!SMgr.isFromMainFile(CP->callEnterWithin.asLocation()))
    return CP;

  const PathPieces &Path = CP->path;
  if (Path.empty())
    return 0;

  // Check if the last piece in the callee path is a call to a function outside
  // of the main file.
  if (PathDiagnosticCallPiece *CPInner =
      dyn_cast<PathDiagnosticCallPiece>(Path.back())) {
    return getFirstStackedCallToHeaderFile(CPInner, SMgr);
  }

  // Otherwise, the last piece is in the main file.
  return 0;
}
Exemple #7
0
void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
                                        DiagnosticsEngine::Level Level,
                                        StringRef Message,
                                        ArrayRef<CharSourceRange> Ranges,
                                        ArrayRef<FixItHint> FixItHints,
                                        const SourceManager *SM,
                                        DiagOrStoredDiag D) {
  assert(SM || Loc.isInvalid());

  beginDiagnostic(D, Level);

  if (!Loc.isValid())
    // If we have no source location, just emit the diagnostic message.
    emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D);
  else {
    // Get the ranges into a local array we can hack on.
    SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(),
                                                   Ranges.end());

    SmallVector<FixItHint, 8> MergedFixits;
    if (!FixItHints.empty()) {
      mergeFixits(FixItHints, *SM, LangOpts, MergedFixits);
      FixItHints = MergedFixits;
    }

    for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(),
         E = FixItHints.end();
         I != E; ++I)
      if (I->RemoveRange.isValid())
        MutableRanges.push_back(I->RemoveRange);

    SourceLocation UnexpandedLoc = Loc;

    // Find the ultimate expansion location for the diagnostic.
    Loc = SM->getFileLoc(Loc);

    PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);

    // First, if this diagnostic is not in the main file, print out the
    // "included from" lines.
    emitIncludeStack(Loc, PLoc, Level, *SM);

    // Next, emit the actual diagnostic message and caret.
    emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D);
    emitCaret(Loc, Level, MutableRanges, FixItHints, *SM);

    // If this location is within a macro, walk from UnexpandedLoc up to Loc
    // and produce a macro backtrace.
    if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) {
      unsigned MacroDepth = 0;
      emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM,
                          MacroDepth);
    }
  }

  LastLoc = Loc;
  LastLevel = Level;

  endDiagnostic(D, Level);
}
/// Finds the tokens that are consecutive (from the same FileID)
/// creates a single SLocEntry, and assigns SourceLocations to each token that
/// point to that SLocEntry. e.g for
///   assert(foo == bar);
/// There will be a single SLocEntry for the "foo == bar" chunk and locations
/// for the 'foo', '==', 'bar' tokens will point inside that chunk.
///
/// \arg begin_tokens will be updated to a position past all the found
/// consecutive tokens.
static void updateConsecutiveMacroArgTokens(SourceManager &SM,
                                            SourceLocation InstLoc,
                                            Token *&begin_tokens,
                                            Token * end_tokens) {
  assert(begin_tokens < end_tokens);

  SourceLocation FirstLoc = begin_tokens->getLocation();
  SourceLocation CurLoc = FirstLoc;

  // Compare the source location offset of tokens and group together tokens that
  // are close, even if their locations point to different FileIDs. e.g.
  //
  //  |bar    |  foo | cake   |  (3 tokens from 3 consecutive FileIDs)
  //  ^                    ^
  //  |bar       foo   cake|     (one SLocEntry chunk for all tokens)
  //
  // we can perform this "merge" since the token's spelling location depends
  // on the relative offset.

  Token *NextTok = begin_tokens + 1;
  for (; NextTok < end_tokens; ++NextTok) {
    SourceLocation NextLoc = NextTok->getLocation();
    if (CurLoc.isFileID() != NextLoc.isFileID())
      break; // Token from different kind of FileID.

    int RelOffs;
    if (!SM.isInSameSLocAddrSpace(CurLoc, NextLoc, &RelOffs))
      break; // Token from different local/loaded location.
    // Check that token is not before the previous token or more than 50
    // "characters" away.
    if (RelOffs < 0 || RelOffs > 50)
      break;

    if (CurLoc.isMacroID() && !SM.isWrittenInSameFile(CurLoc, NextLoc))
      break; // Token from a different macro.

    CurLoc = NextLoc;
  }

  // For the consecutive tokens, find the length of the SLocEntry to contain
  // all of them.
  Token &LastConsecutiveTok = *(NextTok-1);
  int LastRelOffs = 0;
  SM.isInSameSLocAddrSpace(FirstLoc, LastConsecutiveTok.getLocation(),
                           &LastRelOffs);
  unsigned FullLength = LastRelOffs + LastConsecutiveTok.getLength();

  // Create a macro expansion SLocEntry that will "contain" all of the tokens.
  SourceLocation Expansion =
      SM.createMacroArgExpansionLoc(FirstLoc, InstLoc,FullLength);

  // Change the location of the tokens from the spelling location to the new
  // expanded location.
  for (; begin_tokens < NextTok; ++begin_tokens) {
    Token &Tok = *begin_tokens;
    int RelOffs = 0;
    SM.isInSameSLocAddrSpace(FirstLoc, Tok.getLocation(), &RelOffs);
    Tok.setLocation(Expansion.getLocWithOffset(RelOffs));
  }
}
void DeprecatedIosBaseAliasesCheck::check(
    const MatchFinder::MatchResult &Result) {
  SourceManager &SM = *Result.SourceManager;

  const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>("TypeDecl");
  StringRef TypeName = Typedef->getName();
  bool HasReplacement = ReplacementTypes.count(TypeName);

  const auto *TL = Result.Nodes.getNodeAs<TypeLoc>("TypeLoc");
  SourceLocation IoStateLoc = TL->getBeginLoc();

  // Do not generate fixits for matches depending on template arguments and
  // macro expansions.
  bool Fix = HasReplacement && !TL->getType()->isDependentType();
  if (IoStateLoc.isMacroID()) {
    IoStateLoc = SM.getSpellingLoc(IoStateLoc);
    Fix = false;
  }

  SourceLocation EndLoc = IoStateLoc.getLocWithOffset(TypeName.size() - 1);

  if (HasReplacement) {
    auto FixName = ReplacementTypes.lookup(TypeName);
    auto Builder = diag(IoStateLoc, "'std::ios_base::%0' is deprecated; use "
                                    "'std::ios_base::%1' instead")
                   << TypeName << FixName;

    if (Fix)
      Builder << FixItHint::CreateReplacement(SourceRange(IoStateLoc, EndLoc),
                                              FixName);
  } else
    diag(IoStateLoc, "'std::ios_base::%0' is deprecated") << TypeName;
}
Exemple #10
0
PathDiagnosticPiece *
LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
                                                    const ExplodedNode *N,
                                                    BugReport &BR) {
  const Stmt *S = BR.getStmt();
  if (!S)
    return 0;

  // Here we suppress false positives coming from system macros. This list is
  // based on known issues.

  // Skip reports within the sys/queue.h macros as we do not have the ability to
  // reason about data structure shapes.
  SourceManager &SM = BRC.getSourceManager();
  SourceLocation Loc = S->getLocStart();
  while (Loc.isMacroID()) {
    if (SM.isInSystemMacro(Loc) &&
       (SM.getFilename(SM.getSpellingLoc(Loc)).endswith("sys/queue.h"))) {
      BR.markInvalid(getTag(), 0);
      return 0;
    }
    Loc = SM.getSpellingLoc(Loc);
  }

  return 0;
}
void MisleadingIndentationCheck::danglingElseCheck(const SourceManager &SM,
                                                   const IfStmt *If) {
  SourceLocation IfLoc = If->getIfLoc();
  SourceLocation ElseLoc = If->getElseLoc();

  if (IfLoc.isMacroID() || ElseLoc.isMacroID())
    return;

  if (SM.getExpansionLineNumber(If->getThen()->getLocEnd()) ==
      SM.getExpansionLineNumber(ElseLoc))
    return;

  if (SM.getExpansionColumnNumber(IfLoc) !=
      SM.getExpansionColumnNumber(ElseLoc))
    diag(ElseLoc, "different indentation for 'if' and corresponding 'else'");
}
/// A recursive function to trace all possible backtrace locations
/// to match the \p CaretLocFileID.
static SourceLocation retrieveMacroLocation(SourceLocation Loc,
                                            FileID MacroFileID,
                                            FileID CaretFileID,
                                            bool getBeginLoc,
                                            const SourceManager *SM) {
  if (MacroFileID == CaretFileID) return Loc;
  if (!Loc.isMacroID()) return SourceLocation();

  SourceLocation MacroLocation, MacroArgLocation;

  if (SM->isMacroArgExpansion(Loc)) {
    MacroLocation = SM->getImmediateSpellingLoc(Loc);
    MacroArgLocation = getBeginLoc ? SM->getImmediateExpansionRange(Loc).first
                                   : SM->getImmediateExpansionRange(Loc).second;
  } else {
    MacroLocation = getBeginLoc ? SM->getImmediateExpansionRange(Loc).first
                                : SM->getImmediateExpansionRange(Loc).second;
    MacroArgLocation = SM->getImmediateSpellingLoc(Loc);
  }

  MacroFileID = SM->getFileID(MacroLocation);
  MacroLocation = retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID,
                                        getBeginLoc, SM);
  if (MacroLocation.isValid()) return MacroLocation;

  MacroFileID = SM->getFileID(MacroArgLocation);
  return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID,
                               getBeginLoc, SM);
}
/// \brief Computes the source location just past the end of the token at
/// the given source location. If the location points at a macro, the whole
/// macro expansion is skipped.
SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc,
                                                         SourceManager &SM,
                                                         Preprocessor &PP) {
  if (loc.isMacroID())
    loc = SM.getExpansionRange(loc).second;
  return PP.getLocForEndOfToken(loc);
}
/// \brief Retrieve the name of the immediate macro expansion.
///
/// This routine starts from a source location, and finds the name of the macro
/// responsible for its immediate expansion. It looks through any intervening
/// macro argument expansions to compute this. It returns a StringRef which
/// refers to the SourceManager-owned buffer of the source where that macro
/// name is spelled. Thus, the result shouldn't out-live that SourceManager.
///
/// This differs from Lexer::getImmediateMacroName in that any macro argument
/// location will result in the topmost function macro that accepted it.
/// e.g.
/// \code
///   MAC1( MAC2(foo) )
/// \endcode
/// for location of 'foo' token, this function will return "MAC1" while
/// Lexer::getImmediateMacroName will return "MAC2".
static StringRef getImmediateMacroName(SourceLocation Loc,
                                       const SourceManager &SM,
                                       const LangOptions &LangOpts) {
   assert(Loc.isMacroID() && "Only reasonble to call this on macros");
   // Walk past macro argument expanions.
   while (SM.isMacroArgExpansion(Loc))
     Loc = SM.getImmediateExpansionRange(Loc).first;

   // If the macro's spelling has no FileID, then it's actually a token paste
   // or stringization (or similar) and not a macro at all.
   if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc))))
     return StringRef();

   // Find the spelling location of the start of the non-argument expansion
   // range. This is where the macro name was spelled in order to begin
   // expanding this macro.
   Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first);

   // Dig out the buffer where the macro name was spelled and the extents of the
   // name so that we can render it into the expansion note.
   std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc);
   unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts);
   StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first);
   return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
}
/// A helper function to check if the current ranges are all inside the same
/// macro argument expansion as Loc.
static bool checkRangesForMacroArgExpansion(SourceLocation Loc,
                                            ArrayRef<CharSourceRange> Ranges,
                                            const SourceManager &SM) {
  assert(Loc.isMacroID() && "Must be a macro expansion!");

  SmallVector<CharSourceRange, 4> SpellingRanges;
  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);

  /// Count all valid ranges.
  unsigned ValidCount = 0;
  for (auto I : Ranges)
    if (I.isValid()) ValidCount++;

  if (ValidCount > SpellingRanges.size())
    return false;

  /// To store the source location of the argument location.
  SourceLocation ArgumentLoc;

  /// Set the ArgumentLoc to the beginning location of the expansion of Loc
  /// so to check if the ranges expands to the same beginning location.
  if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc))
    return false;

  for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) {
    if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc))
      return false;
  }

  return true;
}
Exemple #16
0
/// \brief \arg Loc is the end of a statement range. This returns the location
/// of the semicolon following the statement.
/// If no semicolon is found or the location is inside a macro, the returned
/// source location will be invalid.
SourceLocation trans::findSemiAfterLocation(SourceLocation loc,
                                            ASTContext &Ctx) {
  SourceManager &SM = Ctx.getSourceManager();
  if (loc.isMacroID()) {
    if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOpts(), &loc))
      return SourceLocation();
  }
  loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOpts());

  // Break down the source location.
  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);

  // Try to load the file buffer.
  bool invalidTemp = false;
  StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
  if (invalidTemp)
    return SourceLocation();

  const char *tokenBegin = file.data() + locInfo.second;

  // Lex from the start of the given location.
  Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
              Ctx.getLangOpts(),
              file.begin(), tokenBegin, file.end());
  Token tok;
  lexer.LexFromRawLexer(tok);
  if (tok.isNot(tok::semi))
    return SourceLocation();

  return tok.getLocation();
}
Exemple #17
0
StringRef CheckerContext::getMacroNameOrSpelling(SourceLocation &Loc) {
  if (Loc.isMacroID())
    return Lexer::getImmediateMacroName(Loc, getSourceManager(),
                                             getLangOpts());
  SmallVector<char, 16> buf;
  return Lexer::getSpelling(Loc, buf, getSourceManager(), getLangOpts());
}
std::vector<FixItHint> QStringAllocations::fixItRawLiteral(clang::StringLiteral *lt, const string &replacement)
{
    vector<FixItHint> fixits;

    SourceRange range = FixItUtils::rangeForLiteral(m_ci, lt);
    if (range.isInvalid()) {
        if (lt) {
            queueManualFixitWarning(lt->getLocStart(), CharPtrAllocations, "Internal error: Can't calculate source location");
        }
        return {};
    }

    SourceLocation start = lt->getLocStart();
    if (start.isMacroID()) {
        queueManualFixitWarning(start, CharPtrAllocations, "Can't use QStringLiteral in macro..");
    } else {
        string revisedReplacement = lt->getLength() == 0 ? "QLatin1String" : replacement; // QLatin1String("") is better than QStringLiteral("")
        if (revisedReplacement == "QStringLiteral" && lt->getLocStart().isMacroID()) {
            queueManualFixitWarning(lt->getLocStart(), CharPtrAllocations, "Can't use QStringLiteral in macro...");
            return {};
        }

        FixItUtils::insertParentMethodCall(revisedReplacement, range, /**by-ref*/fixits);
    }

    return fixits;
}
void MisleadingIndentationCheck::missingBracesCheck(const SourceManager &SM,
                                                    const CompoundStmt *CStmt) {
  const static StringRef StmtNames[] = {"if", "for", "while"};
  for (unsigned int i = 0; i < CStmt->size() - 1; i++) {
    const Stmt *CurrentStmt = CStmt->body_begin()[i];
    const Stmt *Inner = nullptr;
    int StmtKind = 0;

    if (const auto *CurrentIf = dyn_cast<IfStmt>(CurrentStmt)) {
      StmtKind = 0;
      Inner =
          CurrentIf->getElse() ? CurrentIf->getElse() : CurrentIf->getThen();
    } else if (const auto *CurrentFor = dyn_cast<ForStmt>(CurrentStmt)) {
      StmtKind = 1;
      Inner = CurrentFor->getBody();
    } else if (const auto *CurrentWhile = dyn_cast<WhileStmt>(CurrentStmt)) {
      StmtKind = 2;
      Inner = CurrentWhile->getBody();
    } else {
      continue;
    }

    if (isa<CompoundStmt>(Inner))
      continue;

    SourceLocation InnerLoc = Inner->getLocStart();
    SourceLocation OuterLoc = CurrentStmt->getLocStart();

    if (SM.getExpansionLineNumber(InnerLoc) ==
        SM.getExpansionLineNumber(OuterLoc))
      continue;

    const Stmt *NextStmt = CStmt->body_begin()[i + 1];
    SourceLocation NextLoc = NextStmt->getLocStart();

    if (InnerLoc.isMacroID() || OuterLoc.isMacroID() || NextLoc.isMacroID())
      continue;

    if (SM.getExpansionColumnNumber(InnerLoc) ==
        SM.getExpansionColumnNumber(NextLoc)) {
      diag(NextLoc, "misleading indentation: statement is indented too deeply");
      diag(OuterLoc, "did you mean this line to be inside this '%0'",
           DiagnosticIDs::Note)
          << StmtNames[StmtKind];
    }
  }
}
void RemoveUnusedEnumMember::removeEnumConstantDecl()
{
  SourceLocation StartLoc = (*TheEnumIterator)->getLocStart();
  if (StartLoc.isMacroID()) {
    CharSourceRange Range = SrcManager->getExpansionRange(StartLoc);
    StartLoc = Range.getBegin();
  }
  SourceLocation EndLoc = (*TheEnumIterator)->getLocEnd();
  if (EndLoc.isMacroID()) {
    CharSourceRange Range = SrcManager->getExpansionRange(EndLoc);
    EndLoc = Range.getEnd();
  }
  SourceLocation CommaLoc = Lexer::findLocationAfterToken(
    EndLoc, tok::comma, *SrcManager, Context->getLangOpts(),
    /*SkipTrailingWhitespaceAndNewLine=*/false);
  if (CommaLoc.isValid())
    EndLoc = CommaLoc;
  TheRewriter.RemoveText(SourceRange(StartLoc, EndLoc));
}
// Helper function to fix up source ranges.  It takes in an array of ranges,
// and outputs an array of ranges where we want to draw the range highlighting
// around the location specified by CaretLoc.
//
// To find locations which correspond to the caret, we crawl the macro caller
// chain for the beginning and end of each range.  If the caret location
// is in a macro expansion, we search each chain for a location
// in the same expansion as the caret; otherwise, we crawl to the top of
// each chain. Two locations are part of the same macro expansion
// iff the FileID is the same.
static void mapDiagnosticRanges(
    SourceLocation CaretLoc,
    ArrayRef<CharSourceRange> Ranges,
    SmallVectorImpl<CharSourceRange> &SpellingRanges,
    const SourceManager *SM) {
  FileID CaretLocFileID = SM->getFileID(CaretLoc);

  for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
    if (I->isInvalid()) continue;

    SourceLocation Begin = I->getBegin(), End = I->getEnd();
    bool IsTokenRange = I->isTokenRange();

    FileID BeginFileID = SM->getFileID(Begin);
    FileID EndFileID = SM->getFileID(End);

    // Find the common parent for the beginning and end of the range.

    // First, crawl the expansion chain for the beginning of the range.
    llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap;
    while (Begin.isMacroID() && BeginFileID != EndFileID) {
      BeginLocsMap[BeginFileID] = Begin;
      Begin = SM->getImmediateExpansionRange(Begin).first;
      BeginFileID = SM->getFileID(Begin);
    }

    // Then, crawl the expansion chain for the end of the range.
    if (BeginFileID != EndFileID) {
      while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) {
        End = SM->getImmediateExpansionRange(End).second;
        EndFileID = SM->getFileID(End);
      }
      if (End.isMacroID()) {
        Begin = BeginLocsMap[EndFileID];
        BeginFileID = EndFileID;
      }
    }

    // Do the backtracking.
    SmallVector<FileID, 4> CommonArgExpansions;
    computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions);
    Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID,
                                  CommonArgExpansions, /*IsBegin=*/true, SM);
    End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID,
                                CommonArgExpansions, /*IsBegin=*/false, SM);
    if (Begin.isInvalid() || End.isInvalid()) continue;

    // Return the spelling location of the beginning and end of the range.
    Begin = SM->getSpellingLoc(Begin);
    End = SM->getSpellingLoc(End);

    SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End),
                                             IsTokenRange));
  }
}
Exemple #22
0
/// Look through spelling locations for a macro argument expansion, and
/// if found skip to it so that we can trace the argument rather than the macros
/// in which that argument is used. If no macro argument expansion is found,
/// don't skip anything and return the starting location.
static SourceLocation skipToMacroArgExpansion(const SourceManager &SM,
                                                  SourceLocation StartLoc) {
  for (SourceLocation L = StartLoc; L.isMacroID();
       L = SM.getImmediateSpellingLoc(L)) {
    if (SM.isMacroArgInstantiation(L))
      return L;
  }

  // Otherwise just return initial location, there's nothing to skip.
  return StartLoc;
}
Exemple #23
0
/// Get the presumed location of a diagnostic message. This computes the
/// presumed location for the top of any macro backtrace when present.
static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM,
                                            SourceLocation Loc) {
  // This is a condensed form of the algorithm used by EmitCaretDiagnostic to
  // walk to the top of the macro call stack.
  while (Loc.isMacroID()) {
    Loc = skipToMacroArgExpansion(SM, Loc);
    Loc = getImmediateMacroCallerLoc(SM, Loc);
  }

  return SM.getPresumedLoc(Loc);
}
static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM,
                                          SourceLocation Loc) {
  while (true) {
    if (LineIsMarkedWithNOLINT(SM, Loc))
      return true;
    if (!Loc.isMacroID())
      return false;
    Loc = SM.getImmediateExpansionRange(Loc).first;
  }
  return false;
}
void ReplaceAutoPtrCheck::check(const MatchFinder::MatchResult &Result) {
  SourceManager &SM = *Result.SourceManager;
  if (const auto *E =
          Result.Nodes.getNodeAs<Expr>(AutoPtrOwnershipTransferId)) {
    CharSourceRange Range = Lexer::makeFileCharRange(
        CharSourceRange::getTokenRange(E->getSourceRange()), SM, LangOptions());

    if (Range.isInvalid())
      return;

    auto Diag = diag(Range.getBegin(), "use std::move to transfer ownership")
                << FixItHint::CreateInsertion(Range.getBegin(), "std::move(")
                << FixItHint::CreateInsertion(Range.getEnd(), ")");

    if (auto Fix =
            Inserter->CreateIncludeInsertion(SM.getMainFileID(), "utility",
                                             /*IsAngled=*/true))
      Diag << *Fix;

    return;
  }

  SourceLocation AutoPtrLoc;
  if (const auto *TL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) {
    //   std::auto_ptr<int> i;
    //        ^
    if (auto Loc = TL->getAs<TemplateSpecializationTypeLoc>())
      AutoPtrLoc = Loc.getTemplateNameLoc();
  } else if (const auto *D =
                 Result.Nodes.getNodeAs<UsingDecl>(AutoPtrTokenId)) {
    // using std::auto_ptr;
    //            ^
    AutoPtrLoc = D->getNameInfo().getBeginLoc();
  } else {
    llvm_unreachable("Bad Callback. No node provided.");
  }

  if (AutoPtrLoc.isMacroID())
    AutoPtrLoc = SM.getSpellingLoc(AutoPtrLoc);

  // Ensure that only the 'auto_ptr' token is replaced and not the template
  // aliases.
  if (StringRef(SM.getCharacterData(AutoPtrLoc), strlen("auto_ptr")) !=
      "auto_ptr")
    return;

  SourceLocation EndLoc =
      AutoPtrLoc.getLocWithOffset(strlen("auto_ptr") - 1);
  diag(AutoPtrLoc, "auto_ptr is deprecated, use unique_ptr instead")
      << FixItHint::CreateReplacement(SourceRange(AutoPtrLoc, EndLoc),
                                      "unique_ptr");
}
/// Walk up the chain of macro expansions and collect the FileIDs identifying the
/// expansions.
static void getMacroArgExpansionFileIDs(SourceLocation Loc,
                                        SmallVectorImpl<FileID> &IDs,
                                        bool IsBegin, const SourceManager *SM) {
  while (Loc.isMacroID()) {
    if (SM->isMacroArgExpansion(Loc)) {
      IDs.push_back(SM->getFileID(Loc));
      Loc = SM->getImmediateSpellingLoc(Loc);
    } else {
      auto ExpRange = SM->getImmediateExpansionRange(Loc);
      Loc = IsBegin ? ExpRange.first : ExpRange.second;
    }
  }
}
// Looks for the token matching the predicate and returns the range of the found
// token including trailing whitespace.
static SourceRange FindToken(const SourceManager &Sources, LangOptions LangOpts,
                             SourceLocation StartLoc, SourceLocation EndLoc,
                             bool (*Pred)(const Token &)) {
  if (StartLoc.isMacroID() || EndLoc.isMacroID())
    return SourceRange();
  FileID File = Sources.getFileID(Sources.getSpellingLoc(StartLoc));
  StringRef Buf = Sources.getBufferData(File);
  const char *StartChar = Sources.getCharacterData(StartLoc);
  Lexer Lex(StartLoc, LangOpts, StartChar, StartChar, Buf.end());
  Lex.SetCommentRetentionState(true);
  Token Tok;
  do {
    Lex.LexFromRawLexer(Tok);
    if (Pred(Tok)) {
      Token NextTok;
      Lex.LexFromRawLexer(NextTok);
      return SourceRange(Tok.getLocation(), NextTok.getLocation());
    }
  } while (Tok.isNot(tok::eof) && Tok.getLocation() < EndLoc);

  return SourceRange();
}
Exemple #28
0
void SimplifyCommaExpr::simplifyCommaExpr(void)
{
  TransAssert((TheBinaryOperator->getOpcode() == clang::BO_Comma) && 
              "Non Comma Operator!");
  const Expr *LHS = TheBinaryOperator->getLHS();
  std::string LHSStr;
  RewriteHelper->getExprString(LHS, LHSStr);

  SourceRange LHSRange = LHS->getSourceRange();
  SourceLocation StartLoc = LHSRange.getBegin();
  SourceLocation EndLoc;
  if (StartLoc.isMacroID()) {
    StartLoc = SrcManager->getFileLoc(StartLoc);
    EndLoc = LHSRange.getEnd();
    TransAssert(EndLoc.isMacroID() && "EndLoc is not from a macro!");
    LHSRange = SourceRange(StartLoc, SrcManager->getFileLoc(EndLoc));
  }
  EndLoc = RewriteHelper->getEndLocationUntil(LHSRange, ',');
  TheRewriter.RemoveText(SourceRange(StartLoc, EndLoc));

  LHSStr += ";";
  RewriteHelper->addStringBeforeStmt(TheStmt, LHSStr, NeedParen);
}
Exemple #29
0
/// Gets the location of the immediate macro caller, one level up the stack
/// toward the initial macro typed into the source.
static SourceLocation getImmediateMacroCallerLoc(const SourceManager &SM,
                                                 SourceLocation Loc) {
  if (!Loc.isMacroID()) return Loc;

  // When we have the location of (part of) an expanded parameter, its spelling
  // location points to the argument as typed into the macro call, and
  // therefore is used to locate the macro caller.
  if (SM.isMacroArgInstantiation(Loc))
    return SM.getImmediateSpellingLoc(Loc);

  // Otherwise, the caller of the macro is located where this macro is
  // expanded (while the spelling is part of the macro definition).
  return SM.getImmediateInstantiationRange(Loc).first;
}
Exemple #30
0
/// Gets the location of the immediate macro callee, one level down the stack
/// toward the leaf macro.
static SourceLocation getImmediateMacroCalleeLoc(const SourceManager &SM,
                                                 SourceLocation Loc) {
  if (!Loc.isMacroID()) return Loc;

  // When we have the location of (part of) an expanded parameter, its
  // expansion location points to the unexpanded paramater reference within
  // the macro definition (or callee).
  if (SM.isMacroArgInstantiation(Loc))
    return SM.getImmediateInstantiationRange(Loc).first;

  // Otherwise, the callee of the macro is located where this location was
  // spelled inside the macro definition.
  return SM.getImmediateSpellingLoc(Loc);
}