[cfe-commits] r146819 - in /cfe/trunk: include/clang/Frontend/DiagnosticRenderer.h include/clang/Frontend/TextDiagnostic.h lib/Frontend/CMakeLists.txt lib/Frontend/DiagnosticRenderer.cpp lib/Frontend/TextDiagnostic.cpp
Matt Beaumont-Gay
matthewbg at google.com
Thu May 24 16:01:24 PDT 2012
Apologies for the necrothread...
> +/// 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.isMacroArgExpansion(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.isMacroArgExpansion(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.getImmediateExpansionRange(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.isMacroArgExpansion(Loc))
> + return SM.getImmediateExpansionRange(Loc).first;
> +
> + // Otherwise, the callee of the macro is located where this location was
> + // spelled inside the macro definition.
> + return SM.getImmediateSpellingLoc(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.
> +///
> +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;
> +
> + // 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);
> +}
> +
> +/// 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);
> +}
I've recently found myself needing this machinery in a slightly
different context (hacking on a specialized diagnostic client). It
seems like SourceManager might be a natural place for these functions
to be made available to other users. I'm thinking that
getDiagnosticPresumedLoc would be the only new public method, though
possibly under a slightly different name (bikeshed hues welcome). Any
objections to such a refactoring?
-Matt
More information about the cfe-commits
mailing list