diff options
Diffstat (limited to 'lib/Frontend/TextDiagnosticPrinter.cpp')
| -rw-r--r-- | lib/Frontend/TextDiagnosticPrinter.cpp | 115 | 
1 files changed, 94 insertions, 21 deletions
| diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 1c47bf7bee93..e49e19a17c8d 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -292,8 +292,57 @@ static void SelectInterestingSourceRegion(std::string &SourceLine,    }  } -void TextDiagnosticPrinter::EmitCaretDiagnostic(Diagnostic::Level Level, -                                                SourceLocation Loc, +/// 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; +} + +/// 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; +} + +/// 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); +} + +void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,                                                  CharSourceRange *Ranges,                                                  unsigned NumRanges,                                                  const SourceManager &SM, @@ -307,38 +356,46 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(Diagnostic::Level Level,    assert(!Loc.isInvalid() && "must have a valid source location here");    // If this is a macro ID, first emit information about where this was -  // instantiated (recursively) then emit information about where the token was +  // expanded (recursively) then emit information about where the token was    // spelled from.    if (!Loc.isFileID()) { -    // Whether to suppress printing this macro instantiation. +    // Whether to suppress printing this macro expansion.      bool Suppressed         = OnMacroInst >= MacroSkipStart && OnMacroInst < MacroSkipEnd; -     -    SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first; +    // When processing macros, skip over the expansions leading up to +    // a macro argument, and trace the argument's expansion stack instead. +    Loc = skipToMacroArgExpansion(SM, Loc); + +    SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc); +      // FIXME: Map ranges? -    EmitCaretDiagnostic(Level, OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns, +    EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, +                        Hints, NumHints, Columns,                          OnMacroInst + 1, MacroSkipStart, MacroSkipEnd); -     +      // Map the location. -    Loc = SM.getImmediateSpellingLoc(Loc); +    Loc = getImmediateMacroCalleeLoc(SM, Loc);      // Map the ranges.      for (unsigned i = 0; i != NumRanges; ++i) {        CharSourceRange &R = Ranges[i];        SourceLocation S = R.getBegin(), E = R.getEnd();        if (S.isMacroID()) -        R.setBegin(SM.getImmediateSpellingLoc(S)); +        R.setBegin(getImmediateMacroCalleeLoc(SM, S));        if (E.isMacroID()) -        R.setEnd(SM.getImmediateSpellingLoc(E)); +        R.setEnd(getImmediateMacroCalleeLoc(SM, E));      }      if (!Suppressed) { +      // Don't print recursive expansion notes from an expansion note. +      Loc = SM.getSpellingLoc(Loc); +        // Get the pretty name, according to #line directives etc.        PresumedLoc PLoc = SM.getPresumedLoc(Loc);        if (PLoc.isInvalid())          return; -       +        // If this diagnostic is not in the main file, print out the        // "included from" lines.        if (LastWarningLoc != PLoc.getIncludeLoc()) { @@ -353,9 +410,9 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(Diagnostic::Level Level,            OS << PLoc.getColumn() << ':';          OS << ' ';        } -      OS << "note: instantiated from:\n"; -       -      EmitCaretDiagnostic(Level, Loc, Ranges, NumRanges, SM, Hints, NumHints, +      OS << "note: expanded from:\n"; + +      EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, 0, 0,                            Columns, OnMacroInst + 1, MacroSkipStart,                            MacroSkipEnd);        return; @@ -364,13 +421,13 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(Diagnostic::Level Level,      if (OnMacroInst == MacroSkipStart) {        // Tell the user that we've skipped contexts.        OS << "note: (skipping " << (MacroSkipEnd - MacroSkipStart)  -      << " contexts in backtrace; use -fmacro-backtrace-limit=0 to see " +      << " expansions in backtrace; use -fmacro-backtrace-limit=0 to see "        "all)\n";      }      return;    } - +      // Decompose the location into a FID/Offset pair.    std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);    FileID FID = LocInfo.first; @@ -769,6 +826,20 @@ static bool PrintWordWrapped(llvm::raw_ostream &OS,    return true;  } +/// 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); +} +  void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,                                               const DiagnosticInfo &Info) {    // Default implementation (Warnings/errors count). @@ -787,7 +858,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,    // if enabled.    if (Info.getLocation().isValid()) {      const SourceManager &SM = Info.getSourceManager(); -    PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation()); +    PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Info.getLocation());      if (PLoc.isInvalid()) {        // At least print the file name if available:        FileID FID = SM.getFileID(Info.getLocation()); @@ -1040,15 +1111,17 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,        }      } +    const SourceManager &SM = LastLoc.getManager();      unsigned MacroInstSkipStart = 0, MacroInstSkipEnd = 0;      if (DiagOpts && DiagOpts->MacroBacktraceLimit && !LastLoc.isFileID()) { -      // Compute the length of the macro-instantiation backtrace, so that we +      // Compute the length of the macro-expansion backtrace, so that we        // can establish which steps in the macro backtrace we'll skip.        SourceLocation Loc = LastLoc;        unsigned Depth = 0;        do {          ++Depth; -        Loc = LastLoc.getManager().getImmediateInstantiationRange(Loc).first; +        Loc = skipToMacroArgExpansion(SM, Loc); +        Loc = getImmediateMacroCallerLoc(SM, Loc);        } while (!Loc.isFileID());        if (Depth > DiagOpts->MacroBacktraceLimit) { @@ -1058,7 +1131,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,        }      }         -    EmitCaretDiagnostic(Level, LastLoc, Ranges, NumRanges, LastLoc.getManager(), +    EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(),                          Info.getFixItHints(),                          Info.getNumFixItHints(),                          DiagOpts->MessageLength,  | 
