diff options
| author | Chris Lattner <sabre@nondot.org> | 2009-01-27 07:57:44 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2009-01-27 07:57:44 +0000 | 
| commit | f1ca7d3e02e0fb4d5fa6ed56459a31776e82a605 (patch) | |
| tree | 872fc3a12f4820197ea23bf6e061c048bdce7b14 /clang/lib | |
| parent | c360bf2e4868ec6455cea10e26764456098adc5e (diff) | |
| download | bcm5719-llvm-f1ca7d3e02e0fb4d5fa6ed56459a31776e82a605.tar.gz bcm5719-llvm-f1ca7d3e02e0fb4d5fa6ed56459a31776e82a605.zip  | |
Introduce a new PresumedLoc class to represent the concept of a location
as reported to the user and as manipulated by #line.  This is what __FILE__,
__INCLUDE_LEVEL__, diagnostics and other things should follow (but not 
dependency generation!).  
This patch also includes several cleanups along the way: 
- SourceLocation now has a dump method, and several other places 
  that did similar things now use it.
- I cleaned up some code in AnalysisConsumer, but it should probably be
  simplified further now that NamedDecl is better.
- TextDiagnosticPrinter is now simplified and cleaned up a bit.
This patch is a prerequisite for #line, but does not actually provide 
any #line functionality.
llvm-svn: 63098
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/StmtDumper.cpp | 27 | ||||
| -rw-r--r-- | clang/lib/Analysis/LiveVariables.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/Basic/SourceLocation.cpp | 52 | ||||
| -rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 29 | ||||
| -rw-r--r-- | clang/lib/Driver/TextDiagnosticPrinter.cpp | 118 | ||||
| -rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 34 | ||||
| -rw-r--r-- | clang/lib/Lex/Preprocessor.cpp | 12 | 
7 files changed, 151 insertions, 131 deletions
diff --git a/clang/lib/AST/StmtDumper.cpp b/clang/lib/AST/StmtDumper.cpp index 0a7de350d08..83313ed9be9 100644 --- a/clang/lib/AST/StmtDumper.cpp +++ b/clang/lib/AST/StmtDumper.cpp @@ -153,21 +153,26 @@ namespace  {  void StmtDumper::DumpLocation(SourceLocation Loc) {    SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); +   +  if (SpellingLoc.isInvalid()) { +    fprintf(stderr, "<invalid sloc>"); +    return; +  }    // The general format we print out is filename:line:col, but we drop pieces    // that haven't changed since the last loc printed. -  const char *Filename = SM->getSourceName(SpellingLoc); -  unsigned LineNo = SM->getLineNumber(SpellingLoc); -  unsigned ColNo = SM->getColumnNumber(SpellingLoc); -  if (strcmp(Filename, LastLocFilename) != 0) { -    fprintf(stderr, "%s:%u:%u", Filename, LineNo, ColNo); -    LastLocFilename = Filename; -    LastLocLine = LineNo; -  } else if (LineNo != LastLocLine) { -    fprintf(stderr, "line:%u:%u", LineNo, ColNo); -    LastLocLine = LineNo; +  PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc); + +  if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) { +    fprintf(stderr, "%s:%u:%u", PLoc.getFilename(), PLoc.getLine(), +            PLoc.getColumn()); +    LastLocFilename = PLoc.getFilename(); +    LastLocLine = PLoc.getLine(); +  } else if (PLoc.getLine() != LastLocLine) { +    fprintf(stderr, "line:%u:%u", PLoc.getLine(), PLoc.getColumn()); +    LastLocLine = PLoc.getLine();    } else { -    fprintf(stderr, "col:%u", ColNo); +    fprintf(stderr, "col:%u", PLoc.getColumn());    }  } diff --git a/clang/lib/Analysis/LiveVariables.cpp b/clang/lib/Analysis/LiveVariables.cpp index ac0aa9ba8c6..4c86d44e4db 100644 --- a/clang/lib/Analysis/LiveVariables.cpp +++ b/clang/lib/Analysis/LiveVariables.cpp @@ -358,13 +358,9 @@ void LiveVariables::dumpLiveness(const ValTy& V, SourceManager& SM) const {    for (AnalysisDataTy::decl_iterator I = AD.begin_decl(),                                       E = AD.end_decl(); I!=E; ++I)      if (V.getDeclBit(I->second)) {       -      SourceLocation SpellingLoc = SM.getSpellingLoc(I->first->getLocation()); -     -      fprintf(stderr, "  %s <%s:%u:%u>\n",  -              I->first->getIdentifier()->getName(), -              SM.getSourceName(SpellingLoc), -              SM.getLineNumber(SpellingLoc), -              SM.getColumnNumber(SpellingLoc)); +      fprintf(stderr, "  %s <", I->first->getIdentifier()->getName()); +      I->first->getLocation().dump(SM); +      fprintf(stderr, ">\n");      }  }                                   diff --git a/clang/lib/Basic/SourceLocation.cpp b/clang/lib/Basic/SourceLocation.cpp index f0c8274de91..5d484721bd4 100644 --- a/clang/lib/Basic/SourceLocation.cpp +++ b/clang/lib/Basic/SourceLocation.cpp @@ -26,6 +26,29 @@ SourceLocation SourceLocation::ReadVal(llvm::Deserializer& D) {    return SourceLocation::getFromRawEncoding(D.ReadInt());     } +void SourceLocation::dump(const SourceManager &SM) const { +  if (!isValid()) { +    fprintf(stderr, "<invalid loc>"); +    return; +  } +   +  if (isFileID()) { +    PresumedLoc PLoc = SM.getPresumedLoc(*this); +     +    // The instantiation and spelling pos is identical for file locs. +    fprintf(stderr, "%s:%d:%d", +            PLoc.getFilename(), PLoc.getLine(), PLoc.getColumn()); +    return; +  } +   +  SM.getInstantiationLoc(*this).dump(SM); +   +  fprintf(stderr, " <Spelling="); +  SM.getSpellingLoc(*this).dump(SM); +  fprintf(stderr, ">"); +} + +  void SourceRange::Emit(llvm::Serializer& S) const {    B.Emit(S);    E.Emit(S); @@ -53,11 +76,6 @@ FullSourceLoc FullSourceLoc::getSpellingLoc() const {    return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr);  } -FullSourceLoc FullSourceLoc::getIncludeLoc() const { -  assert(isValid()); -  return FullSourceLoc(SrcMgr->getIncludeLoc(*this), *SrcMgr); -} -  unsigned FullSourceLoc::getLineNumber() const {    assert(isValid());    return SrcMgr->getLineNumber(*this); @@ -89,11 +107,6 @@ unsigned FullSourceLoc::getSpellingColumnNumber() const {    return SrcMgr->getSpellingColumnNumber(*this);  } -const char* FullSourceLoc::getSourceName() const { -  assert(isValid()); -  return SrcMgr->getSourceName(*this); -} -  bool FullSourceLoc::isInSystemHeader() const {    assert(isValid());    return SrcMgr->isInSystemHeader(*this); @@ -109,22 +122,3 @@ const llvm::MemoryBuffer* FullSourceLoc::getBuffer() const {    return SrcMgr->getBuffer(SrcMgr->getFileID(*this));  } -void FullSourceLoc::dump() const { -  if (!isValid()) { -    fprintf(stderr, "Invalid Loc\n"); -    return; -  } -   -  if (isFileID()) { -    // The instantiation and spelling pos is identical for file locs. -    fprintf(stderr, "File Loc from '%s': %d: %d\n", -            getSourceName(), getInstantiationLineNumber(), -            getInstantiationColumnNumber()); -  } else { -    fprintf(stderr, "Macro Loc (\n  Spelling: "); -    getSpellingLoc().dump(); -    fprintf(stderr, "  Instantiation: "); -    getInstantiationLoc().dump(); -    fprintf(stderr, ")\n"); -  } -} diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 9b509a56845..88292cd42bd 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -552,18 +552,31 @@ unsigned SourceManager::getLineNumber(SourceLocation Loc) const {    return LineNo;  } -/// getSourceName - This method returns the name of the file or buffer that -/// the SourceLocation specifies.  This can be modified with #line directives, -/// etc. -const char *SourceManager::getSourceName(SourceLocation Loc) const { -  if (Loc.isInvalid()) return ""; +/// getPresumedLoc - This method returns the "presumed" location of a +/// SourceLocation specifies.  A "presumed location" can be modified by #line +/// or GNU line marker directives.  This provides a view on the data that a +/// user should see in diagnostics, for example. +/// +/// Note that a presumed location is always given as the instantiation point +/// of an instantiation location, not at the spelling location. +PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { +  if (Loc.isInvalid()) return PresumedLoc(); +   +  // Presumed locations are always for instantiation points. +  Loc = getInstantiationLoc(Loc); -  const SrcMgr::ContentCache *C = -  getSLocEntry(getFileID(getSpellingLoc(Loc))).getFile().getContentCache(); +  // FIXME: Could just decompose Loc once! +  const SrcMgr::FileInfo &FI = getSLocEntry(getFileID(Loc)).getFile(); +  const SrcMgr::ContentCache *C = FI.getContentCache(); +    // To get the source name, first consult the FileEntry (if one exists) before    // the MemBuffer as this will avoid unnecessarily paging in the MemBuffer. -  return C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier(); +  const char *Filename =  +    C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier(); +   +  return PresumedLoc(Filename, getLineNumber(Loc), getColumnNumber(Loc), +                     FI.getIncludeLoc());  }  //===----------------------------------------------------------------------===// diff --git a/clang/lib/Driver/TextDiagnosticPrinter.cpp b/clang/lib/Driver/TextDiagnosticPrinter.cpp index 71a5e401075..b19d61c160f 100644 --- a/clang/lib/Driver/TextDiagnosticPrinter.cpp +++ b/clang/lib/Driver/TextDiagnosticPrinter.cpp @@ -15,28 +15,26 @@  #include "clang/Basic/SourceManager.h"  #include "clang/Lex/Lexer.h"  #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/MemoryBuffer.h"  #include "llvm/ADT/SmallString.h"  using namespace clang;  void TextDiagnosticPrinter:: -PrintIncludeStack(FullSourceLoc Pos) { -  if (Pos.isInvalid()) return; +PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) { +  if (Loc.isInvalid()) return; -  Pos = Pos.getInstantiationLoc(); +  PresumedLoc PLoc = SM.getPresumedLoc(Loc);    // Print out the other include frames first. -  PrintIncludeStack(Pos.getIncludeLoc()); -  unsigned LineNo = Pos.getLineNumber(); +  PrintIncludeStack(PLoc.getIncludeLoc(), SM); -  OS << "In file included from " << Pos.getSourceName() -     << ':' << LineNo << ":\n"; +  OS << "In file included from " << PLoc.getFilename() +     << ':' << PLoc.getLine() << ":\n";  }  /// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)  /// any characters in LineNo that intersect the SourceRange.  void TextDiagnosticPrinter::HighlightRange(const SourceRange &R, -                                           const SourceManager &SourceMgr, +                                           const SourceManager &SM,                                             unsigned LineNo, FileID FID,                                             std::string &CaretLine,                                             const std::string &SourceLine) { @@ -44,23 +42,21 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,           "Expect a correspondence between source and caret line!");    if (!R.isValid()) return; -  SourceLocation InstantiationStart = -    SourceMgr.getInstantiationLoc(R.getBegin()); -  unsigned StartLineNo = SourceMgr.getLineNumber(InstantiationStart); -  if (StartLineNo > LineNo || -      SourceMgr.getFileID(InstantiationStart) != FID) +  SourceLocation Begin = SM.getInstantiationLoc(R.getBegin()); +  SourceLocation End = SM.getInstantiationLoc(R.getEnd()); +   +  unsigned StartLineNo = SM.getLineNumber(Begin); +  if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)      return;  // No intersection. -  SourceLocation InstantiationEnd = SourceMgr.getInstantiationLoc(R.getEnd()); -  unsigned EndLineNo = SourceMgr.getLineNumber(InstantiationEnd); -  if (EndLineNo < LineNo || -      SourceMgr.getFileID(InstantiationEnd) != FID) +  unsigned EndLineNo = SM.getLineNumber(End); +  if (EndLineNo < LineNo || SM.getFileID(End) != FID)      return;  // No intersection.    // Compute the column number of the start.    unsigned StartColNo = 0;    if (StartLineNo == LineNo) { -    StartColNo = SourceMgr.getInstantiationColumnNumber(R.getBegin()); +    StartColNo = SM.getColumnNumber(Begin);      if (StartColNo) --StartColNo;  // Zero base the col #.    } @@ -72,12 +68,12 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,    // Compute the column number of the end.    unsigned EndColNo = CaretLine.size();    if (EndLineNo == LineNo) { -    EndColNo = SourceMgr.getInstantiationColumnNumber(R.getEnd()); +    EndColNo = SM.getColumnNumber(End);      if (EndColNo) {        --EndColNo;  // Zero base the col #.        // Add in the length of the token, so that we cover multi-char tokens. -      EndColNo += Lexer::MeasureTokenLength(R.getEnd(), SourceMgr); +      EndColNo += Lexer::MeasureTokenLength(End, SM);      } else {        EndColNo = CaretLine.size();      } @@ -99,39 +95,25 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,  void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,                                                const DiagnosticInfo &Info) { -  unsigned LineNo = 0, ColNo = 0; -  FileID FID; -  const char *LineStart = 0, *LineEnd = 0; -  const FullSourceLoc &Pos = Info.getLocation(); +  const SourceManager &SM = Info.getLocation().getManager(); +  unsigned ColNo = 0; -  if (Pos.isValid()) { -    FullSourceLoc LPos = Pos.getInstantiationLoc(); -    FID = LPos.getFileID(); -    LineNo = LPos.getLineNumber(); +  // If the location is specified, print out a file/line/col and include trace +  // if enabled. +  if (Info.getLocation().isValid()) { +    PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation()); +    unsigned LineNo = PLoc.getLine();      // First, if this diagnostic is not in the main file, print out the      // "included from" lines. -    if (LastWarningLoc != LPos.getIncludeLoc()) { -      LastWarningLoc = LPos.getIncludeLoc(); -      PrintIncludeStack(LastWarningLoc); +    if (LastWarningLoc != PLoc.getIncludeLoc()) { +      LastWarningLoc = PLoc.getIncludeLoc(); +      PrintIncludeStack(LastWarningLoc, SM);      } -    // Compute the column number.  Rewind from the current position to the start -    // of the line. -    ColNo = LPos.getColumnNumber(); -    const char *TokInstantiationPtr = LPos.getCharacterData(); -    LineStart = TokInstantiationPtr-ColNo+1;  // Column # is 1-based - -    // Compute the line end.  Scan forward from the error position to the end of -    // the line. -    const llvm::MemoryBuffer *Buffer = LPos.getBuffer(); -    const char *BufEnd = Buffer->getBufferEnd(); -    LineEnd = TokInstantiationPtr; -    while (LineEnd != BufEnd &&  -           *LineEnd != '\n' && *LineEnd != '\r') -      ++LineEnd; -   -    OS << Buffer->getBufferIdentifier() << ':' << LineNo << ':'; +    // Compute the column number. +    ColNo = PLoc.getColumn(); +    OS << PLoc.getFilename() << ':' << LineNo << ':';      if (ColNo && ShowColumn)         OS << ColNo << ':';      OS << ' '; @@ -149,21 +131,49 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,    OS.write(OutStr.begin(), OutStr.size());    OS << '\n'; -  if (CaretDiagnostics && Pos.isValid() && -      ((LastLoc != Pos) || Info.getNumRanges())) { +  // If caret diagnostics are enabled and we have location, we want to emit the +  // caret.  However, we only do this if the location moved from the last +  // diagnostic, or if the diagnostic has ranges.  We don't want to emit the +  // same caret multiple times if one loc has multiple diagnostics. +  if (CaretDiagnostics && Info.getLocation().isValid() && +      ((LastLoc != Info.getLocation()) || Info.getNumRanges())) {      // Cache the LastLoc, it allows us to omit duplicate source/caret spewage. -    LastLoc = Pos; +    LastLoc = Info.getLocation(); + +    // Inspect the actual instantiation point of the diagnostic, we don't care +    // about presumed locations anymore. +    SourceLocation ILoc = SM.getInstantiationLoc(Info.getLocation()); +     +    // Get the file and line that we want to highlight.  We only draw ranges +    // that intersect this. +    FileID ILocFID = SM.getFileID(ILoc); +    unsigned LineNo = SM.getLineNumber(ILoc); -    // Get the line of the source file. +    // Get the line of the source file.  Scan from the location backward and +    // forward to find the start/end of the line. +     +    // Rewind from the current position to the start of the line. +    const char *TokInstantiationPtr = SM.getCharacterData(ILoc); +    const char *LineStart = TokInstantiationPtr-ColNo+1; // Column # is 1-based. +     +    // Compute the line end.  Scan forward from the error position to the end of +    // the line. +    const char *BufEnd = SM.getBufferData(ILocFID).second; +    const char *LineEnd = TokInstantiationPtr; +    while (LineEnd != BufEnd &&  +           *LineEnd != '\n' && *LineEnd != '\r') +      ++LineEnd; +     +    // Copy the line of code into an std::string for ease of manipulation.      std::string SourceLine(LineStart, LineEnd);      // Create a line for the caret that is filled with spaces that is the same      // length as the line of source code.      std::string CaretLine(LineEnd-LineStart, ' '); -     +      // Highlight all of the characters covered by Ranges with ~ characters.      for (unsigned i = 0; i != Info.getNumRanges(); ++i) -      HighlightRange(Info.getRange(i), Pos.getManager(), LineNo, FID, +      HighlightRange(Info.getRange(i), SM, LineNo, ILocFID,                       CaretLine, SourceLine);      // Next, insert the caret itself. diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 8eada6003d8..a517b1d4f56 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -454,28 +454,37 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {    Tok.clearFlag(Token::NeedsCleaning);    if (II == Ident__LINE__) { +    // C99 6.10.8: "__LINE__: The presumed line number (within the current +    // source file) of the current source line (an integer constant)".  This can +    // be affected by #line. +    PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); +          // __LINE__ expands to a simple numeric value.  Add a space after it so that      // it will tokenize as a number (and not run into stuff after it in the temp      // buffer). -    sprintf(TmpBuffer, "%u ", -            SourceMgr.getInstantiationLineNumber(Tok.getLocation())); +    sprintf(TmpBuffer, "%u ", PLoc.getLine());      unsigned Length = strlen(TmpBuffer)-1;      Tok.setKind(tok::numeric_constant);      CreateString(TmpBuffer, Length+1, Tok, Tok.getLocation());      Tok.setLength(Length);  // Trim off space.    } else if (II == Ident__FILE__ || II == Ident__BASE_FILE__) { -    SourceLocation Loc = Tok.getLocation(); +    // C99 6.10.8: "__FILE__: The presumed name of the current source file (a +    // character string literal)". This can be affected by #line. +    PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); + +    // __BASE_FILE__ is a GNU extension that returns the top of the presumed +    // #include stack instead of the current file.      if (II == Ident__BASE_FILE__) {        Diag(Tok, diag::ext_pp_base_file); -      SourceLocation NextLoc = SourceMgr.getIncludeLoc(Loc); +      SourceLocation NextLoc = PLoc.getIncludeLoc();        while (NextLoc.isValid()) { -        Loc = NextLoc; -        NextLoc = SourceMgr.getIncludeLoc(Loc); +        PLoc = SourceMgr.getPresumedLoc(NextLoc); +        NextLoc = PLoc.getIncludeLoc();        }      }      // Escape this filename.  Turn '\' -> '\\' '"' -> '\"' -    std::string FN =SourceMgr.getSourceName(SourceMgr.getInstantiationLoc(Loc)); +    std::string FN = PLoc.getFilename();      FN = '"' + Lexer::Stringify(FN) + '"';      Tok.setKind(tok::string_literal);      CreateString(&FN[0], FN.size(), Tok, Tok.getLocation()); @@ -496,11 +505,14 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {    } else if (II == Ident__INCLUDE_LEVEL__) {      Diag(Tok, diag::ext_pp_include_level); -    // Compute the include depth of this token. +    // Compute the presumed include depth of this token.  This can be affected +    // by GNU line markers.      unsigned Depth = 0; -    SourceLocation Loc = SourceMgr.getIncludeLoc(Tok.getLocation()); -    for (; Loc.isValid(); ++Depth) -      Loc = SourceMgr.getIncludeLoc(Loc); +     +    PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); +    PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc()); +    for (; PLoc.isValid(); ++Depth) +      PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc());      // __INCLUDE_LEVEL__ expands to a simple numeric value.  Add a space after      // it so that it will tokenize as a number (and not run into stuff after it diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index e6bf1777a89..48fdd68ab9b 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -142,17 +142,7 @@ void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {  }  void Preprocessor::DumpLocation(SourceLocation Loc) const { -  SourceLocation LogLoc = SourceMgr.getInstantiationLoc(Loc); -  llvm::cerr << SourceMgr.getSourceName(LogLoc) << ':' -             << SourceMgr.getLineNumber(LogLoc) << ':' -             << SourceMgr.getColumnNumber(LogLoc); -   -  SourceLocation SpellingLoc = SourceMgr.getSpellingLoc(Loc); -  if (SpellingLoc != LogLoc) { -    llvm::cerr << " <SpellingLoc="; -    DumpLocation(SpellingLoc); -    llvm::cerr << ">"; -  } +  Loc.dump(SourceMgr);  }  void Preprocessor::DumpMacro(const MacroInfo &MI) const {  | 

