LLVM  3.7.0
CoverageMapping.cpp
Go to the documentation of this file.
1 //=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains support for clang's and llvm's instrumentation based
11 // code coverage.
12 //
13 //===----------------------------------------------------------------------===//
14 
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/Optional.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/Errc.h"
25 #include "llvm/Support/Path.h"
27 
28 using namespace llvm;
29 using namespace coverage;
30 
31 #define DEBUG_TYPE "coverage-mapping"
32 
33 Counter CounterExpressionBuilder::get(const CounterExpression &E) {
34  auto It = ExpressionIndices.find(E);
35  if (It != ExpressionIndices.end())
36  return Counter::getExpression(It->second);
37  unsigned I = Expressions.size();
38  Expressions.push_back(E);
39  ExpressionIndices[E] = I;
40  return Counter::getExpression(I);
41 }
42 
43 void CounterExpressionBuilder::extractTerms(
44  Counter C, int Sign, SmallVectorImpl<std::pair<unsigned, int>> &Terms) {
45  switch (C.getKind()) {
46  case Counter::Zero:
47  break;
49  Terms.push_back(std::make_pair(C.getCounterID(), Sign));
50  break;
52  const auto &E = Expressions[C.getExpressionID()];
53  extractTerms(E.LHS, Sign, Terms);
54  extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign,
55  Terms);
56  break;
57  }
58 }
59 
60 Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
61  // Gather constant terms.
63  extractTerms(ExpressionTree, +1, Terms);
64 
65  // If there are no terms, this is just a zero. The algorithm below assumes at
66  // least one term.
67  if (Terms.size() == 0)
68  return Counter::getZero();
69 
70  // Group the terms by counter ID.
71  std::sort(Terms.begin(), Terms.end(),
72  [](const std::pair<unsigned, int> &LHS,
73  const std::pair<unsigned, int> &RHS) {
74  return LHS.first < RHS.first;
75  });
76 
77  // Combine terms by counter ID to eliminate counters that sum to zero.
78  auto Prev = Terms.begin();
79  for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
80  if (I->first == Prev->first) {
81  Prev->second += I->second;
82  continue;
83  }
84  ++Prev;
85  *Prev = *I;
86  }
87  Terms.erase(++Prev, Terms.end());
88 
89  Counter C;
90  // Create additions. We do this before subtractions to avoid constructs like
91  // ((0 - X) + Y), as opposed to (Y - X).
92  for (auto Term : Terms) {
93  if (Term.second <= 0)
94  continue;
95  for (int I = 0; I < Term.second; ++I)
96  if (C.isZero())
97  C = Counter::getCounter(Term.first);
98  else
100  Counter::getCounter(Term.first)));
101  }
102 
103  // Create subtractions.
104  for (auto Term : Terms) {
105  if (Term.second >= 0)
106  continue;
107  for (int I = 0; I < -Term.second; ++I)
109  Counter::getCounter(Term.first)));
110  }
111  return C;
112 }
113 
115  return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
116 }
117 
119  return simplify(
121 }
122 
124  llvm::raw_ostream &OS) const {
125  switch (C.getKind()) {
126  case Counter::Zero:
127  OS << '0';
128  return;
130  OS << '#' << C.getCounterID();
131  break;
132  case Counter::Expression: {
133  if (C.getExpressionID() >= Expressions.size())
134  return;
135  const auto &E = Expressions[C.getExpressionID()];
136  OS << '(';
137  dump(E.LHS, OS);
138  OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
139  dump(E.RHS, OS);
140  OS << ')';
141  break;
142  }
143  }
144  if (CounterValues.empty())
145  return;
147  if (!Value)
148  return;
149  OS << '[' << *Value << ']';
150 }
151 
153  switch (C.getKind()) {
154  case Counter::Zero:
155  return 0;
157  if (C.getCounterID() >= CounterValues.size())
159  return CounterValues[C.getCounterID()];
160  case Counter::Expression: {
161  if (C.getExpressionID() >= Expressions.size())
163  const auto &E = Expressions[C.getExpressionID()];
164  ErrorOr<int64_t> LHS = evaluate(E.LHS);
165  if (!LHS)
166  return LHS;
167  ErrorOr<int64_t> RHS = evaluate(E.RHS);
168  if (!RHS)
169  return RHS;
170  return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
171  }
172  }
173  llvm_unreachable("Unhandled CounterKind");
174 }
175 
176 void FunctionRecordIterator::skipOtherFiles() {
177  while (Current != Records.end() && !Filename.empty() &&
178  Filename != Current->Filenames[0])
179  ++Current;
180  if (Current == Records.end())
181  *this = FunctionRecordIterator();
182 }
183 
184 /// Get the function name from the record, removing the filename prefix if
185 /// necessary.
187  StringRef FunctionName = Record.FunctionName;
188  if (Record.Filenames.empty())
189  return FunctionName;
190  StringRef Filename = sys::path::filename(Record.Filenames[0]);
191  if (FunctionName.startswith(Filename))
192  FunctionName = FunctionName.drop_front(Filename.size() + 1);
193  return FunctionName;
194 }
195 
198  IndexedInstrProfReader &ProfileReader) {
199  auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
200 
201  std::vector<uint64_t> Counts;
202  for (const auto &Record : CoverageReader) {
203  CounterMappingContext Ctx(Record.Expressions);
204 
205  Counts.clear();
206  if (std::error_code EC = ProfileReader.getFunctionCounts(
207  Record.FunctionName, Record.FunctionHash, Counts)) {
208  if (EC == instrprof_error::hash_mismatch) {
209  Coverage->MismatchedFunctionCount++;
210  continue;
211  } else if (EC != instrprof_error::unknown_function)
212  return EC;
213  Counts.assign(Record.MappingRegions.size(), 0);
214  }
215  Ctx.setCounts(Counts);
216 
217  assert(!Record.MappingRegions.empty() && "Function has no regions");
218 
220  for (const auto &Region : Record.MappingRegions) {
221  ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
222  if (!ExecutionCount)
223  break;
224  Function.pushRegion(Region, *ExecutionCount);
225  }
226  if (Function.CountedRegions.size() != Record.MappingRegions.size()) {
227  Coverage->MismatchedFunctionCount++;
228  continue;
229  }
230 
231  Coverage->Functions.push_back(std::move(Function));
232  }
233 
234  return std::move(Coverage);
235 }
236 
238 CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename,
239  StringRef Arch) {
240  auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
241  if (std::error_code EC = CounterMappingBuff.getError())
242  return EC;
243  auto CoverageReaderOrErr =
244  BinaryCoverageReader::create(CounterMappingBuff.get(), Arch);
245  if (std::error_code EC = CoverageReaderOrErr.getError())
246  return EC;
247  auto CoverageReader = std::move(CoverageReaderOrErr.get());
248  auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
249  if (auto EC = ProfileReaderOrErr.getError())
250  return EC;
251  auto ProfileReader = std::move(ProfileReaderOrErr.get());
252  return load(*CoverageReader, *ProfileReader);
253 }
254 
255 namespace {
256 /// \brief Distributes functions into instantiation sets.
257 ///
258 /// An instantiation set is a collection of functions that have the same source
259 /// code, ie, template functions specializations.
260 class FunctionInstantiationSetCollector {
262  std::vector<const FunctionRecord *>> MapT;
263  MapT InstantiatedFunctions;
264 
265 public:
266  void insert(const FunctionRecord &Function, unsigned FileID) {
267  auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
268  while (I != E && I->FileID != FileID)
269  ++I;
270  assert(I != E && "function does not cover the given file");
271  auto &Functions = InstantiatedFunctions[I->startLoc()];
272  Functions.push_back(&Function);
273  }
274 
275  MapT::iterator begin() { return InstantiatedFunctions.begin(); }
276 
277  MapT::iterator end() { return InstantiatedFunctions.end(); }
278 };
279 
280 class SegmentBuilder {
281  std::vector<CoverageSegment> Segments;
283 
284  /// Start a segment with no count specified.
285  void startSegment(unsigned Line, unsigned Col) {
286  DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n");
287  Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false);
288  }
289 
290  /// Start a segment with the given Region's count.
291  void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry,
292  const CountedRegion &Region) {
293  if (Segments.empty())
294  Segments.emplace_back(Line, Col, IsRegionEntry);
295  CoverageSegment S = Segments.back();
296  // Avoid creating empty regions.
297  if (S.Line != Line || S.Col != Col) {
298  Segments.emplace_back(Line, Col, IsRegionEntry);
299  S = Segments.back();
300  }
301  DEBUG(dbgs() << "Segment at " << Line << ":" << Col);
302  // Set this region's count.
304  DEBUG(dbgs() << " with count " << Region.ExecutionCount);
305  Segments.back().setCount(Region.ExecutionCount);
306  }
307  DEBUG(dbgs() << "\n");
308  }
309 
310  /// Start a segment for the given region.
311  void startSegment(const CountedRegion &Region) {
312  startSegment(Region.LineStart, Region.ColumnStart, true, Region);
313  }
314 
315  /// Pop the top region off of the active stack, starting a new segment with
316  /// the containing Region's count.
317  void popRegion() {
318  const CountedRegion *Active = ActiveRegions.back();
319  unsigned Line = Active->LineEnd, Col = Active->ColumnEnd;
320  ActiveRegions.pop_back();
321  if (ActiveRegions.empty())
322  startSegment(Line, Col);
323  else
324  startSegment(Line, Col, false, *ActiveRegions.back());
325  }
326 
327 public:
328  /// Build a list of CoverageSegments from a sorted list of Regions.
329  std::vector<CoverageSegment> buildSegments(ArrayRef<CountedRegion> Regions) {
330  const CountedRegion *PrevRegion = nullptr;
331  for (const auto &Region : Regions) {
332  // Pop any regions that end before this one starts.
333  while (!ActiveRegions.empty() &&
334  ActiveRegions.back()->endLoc() <= Region.startLoc())
335  popRegion();
336  if (PrevRegion && PrevRegion->startLoc() == Region.startLoc() &&
337  PrevRegion->endLoc() == Region.endLoc()) {
339  Segments.back().addCount(Region.ExecutionCount);
340  } else {
341  // Add this region to the stack.
342  ActiveRegions.push_back(&Region);
343  startSegment(Region);
344  }
345  PrevRegion = &Region;
346  }
347  // Pop any regions that are left in the stack.
348  while (!ActiveRegions.empty())
349  popRegion();
350  return Segments;
351  }
352 };
353 }
354 
355 std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
356  std::vector<StringRef> Filenames;
357  for (const auto &Function : getCoveredFunctions())
358  Filenames.insert(Filenames.end(), Function.Filenames.begin(),
359  Function.Filenames.end());
360  std::sort(Filenames.begin(), Filenames.end());
361  auto Last = std::unique(Filenames.begin(), Filenames.end());
362  Filenames.erase(Last, Filenames.end());
363  return Filenames;
364 }
365 
367  const FunctionRecord &Function) {
368  SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
369  for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
370  if (SourceFile == Function.Filenames[I])
371  FilenameEquivalence[I] = true;
372  return FilenameEquivalence;
373 }
374 
376  const FunctionRecord &Function) {
377  SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
378  SmallBitVector FilenameEquivalence = gatherFileIDs(SourceFile, Function);
379  for (const auto &CR : Function.CountedRegions)
380  if (CR.Kind == CounterMappingRegion::ExpansionRegion &&
381  FilenameEquivalence[CR.FileID])
382  IsNotExpandedFile[CR.ExpandedFileID] = false;
383  IsNotExpandedFile &= FilenameEquivalence;
384  int I = IsNotExpandedFile.find_first();
385  if (I == -1)
386  return None;
387  return I;
388 }
389 
391  SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
392  for (const auto &CR : Function.CountedRegions)
394  IsNotExpandedFile[CR.ExpandedFileID] = false;
395  int I = IsNotExpandedFile.find_first();
396  if (I == -1)
397  return None;
398  return I;
399 }
400 
401 /// Sort a nested sequence of regions from a single file.
402 template <class It> static void sortNestedRegions(It First, It Last) {
403  std::sort(First, Last,
404  [](const CountedRegion &LHS, const CountedRegion &RHS) {
405  if (LHS.startLoc() == RHS.startLoc())
406  // When LHS completely contains RHS, we sort LHS first.
407  return RHS.endLoc() < LHS.endLoc();
408  return LHS.startLoc() < RHS.startLoc();
409  });
410 }
411 
412 static bool isExpansion(const CountedRegion &R, unsigned FileID) {
413  return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
414 }
415 
417  CoverageData FileCoverage(Filename);
418  std::vector<coverage::CountedRegion> Regions;
419 
420  for (const auto &Function : Functions) {
421  auto MainFileID = findMainViewFileID(Filename, Function);
422  if (!MainFileID)
423  continue;
424  auto FileIDs = gatherFileIDs(Filename, Function);
425  for (const auto &CR : Function.CountedRegions)
426  if (FileIDs.test(CR.FileID)) {
427  Regions.push_back(CR);
428  if (isExpansion(CR, *MainFileID))
429  FileCoverage.Expansions.emplace_back(CR, Function);
430  }
431  }
432 
433  sortNestedRegions(Regions.begin(), Regions.end());
434  DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
435  FileCoverage.Segments = SegmentBuilder().buildSegments(Regions);
436 
437  return FileCoverage;
438 }
439 
440 std::vector<const FunctionRecord *>
442  FunctionInstantiationSetCollector InstantiationSetCollector;
443  for (const auto &Function : Functions) {
444  auto MainFileID = findMainViewFileID(Filename, Function);
445  if (!MainFileID)
446  continue;
447  InstantiationSetCollector.insert(Function, *MainFileID);
448  }
449 
450  std::vector<const FunctionRecord *> Result;
451  for (const auto &InstantiationSet : InstantiationSetCollector) {
452  if (InstantiationSet.second.size() < 2)
453  continue;
454  Result.insert(Result.end(), InstantiationSet.second.begin(),
455  InstantiationSet.second.end());
456  }
457  return Result;
458 }
459 
462  auto MainFileID = findMainViewFileID(Function);
463  if (!MainFileID)
464  return CoverageData();
465 
466  CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
467  std::vector<coverage::CountedRegion> Regions;
468  for (const auto &CR : Function.CountedRegions)
469  if (CR.FileID == *MainFileID) {
470  Regions.push_back(CR);
471  if (isExpansion(CR, *MainFileID))
472  FunctionCoverage.Expansions.emplace_back(CR, Function);
473  }
474 
475  sortNestedRegions(Regions.begin(), Regions.end());
476  DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n");
477  FunctionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
478 
479  return FunctionCoverage;
480 }
481 
484  CoverageData ExpansionCoverage(
485  Expansion.Function.Filenames[Expansion.FileID]);
486  std::vector<coverage::CountedRegion> Regions;
487  for (const auto &CR : Expansion.Function.CountedRegions)
488  if (CR.FileID == Expansion.FileID) {
489  Regions.push_back(CR);
490  if (isExpansion(CR, Expansion.FileID))
491  ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
492  }
493 
494  sortNestedRegions(Regions.begin(), Regions.end());
495  DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID
496  << "\n");
497  ExpansionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
498 
499  return ExpansionCoverage;
500 }
501 
502 namespace {
503 class CoverageMappingErrorCategoryType : public std::error_category {
504  const char *name() const LLVM_NOEXCEPT override { return "llvm.coveragemap"; }
505  std::string message(int IE) const override {
506  auto E = static_cast<coveragemap_error>(IE);
507  switch (E) {
509  return "Success";
511  return "End of File";
513  return "No coverage data found";
515  return "Unsupported coverage format version";
517  return "Truncated coverage data";
519  return "Malformed coverage data";
520  }
521  llvm_unreachable("A value of coveragemap_error has no message.");
522  }
523 };
524 }
525 
527 
529  return *ErrorCategory;
530 }
const NoneType None
Definition: None.h:23
static void sortNestedRegions(It First, It Last)
Sort a nested sequence of regions from a single file.
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:240
Represents either an error or a value T.
Definition: ErrorOr.h:82
const std::error_category & coveragemap_category()
SmallBitVector - This is a 'bitvector' (really, a variable-sized bit array), optimized for the case w...
size_t size() const
size - Get the string size.
Definition: StringRef.h:113
static Counter getZero()
Return the counter that represents the number zero.
void setCounts(ArrayRef< uint64_t > Counts)
static SmallBitVector gatherFileIDs(StringRef SourceFile, const FunctionRecord &Function)
std::vector< const FunctionRecord * > getInstantiations(StringRef Filename)
Get the list of function instantiations in the file.
const_iterator begin(StringRef path)
Get begin iterator over path.
Definition: Path.cpp:232
static ErrorOr< std::unique_ptr< CoverageMapping > > load(CoverageMappingReader &CoverageReader, IndexedInstrProfReader &ProfileReader)
Load the coverage mapping using the given readers.
A Counter expression is a value that represents an arithmetic operation with two counters.
CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion)
Get the coverage for an expansion within a coverage set.
ErrorOr< int64_t > evaluate(const Counter &C) const
Return the number of times that a region of code associated with this counter was executed...
unsigned Col
The column where this segment begins.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APInt.h:33
std::error_code make_error_code(BitcodeError E)
Definition: ReaderWriter.h:150
#define LLVM_NOEXCEPT
Definition: Compiler.h:70
Coverage information to be processed or displayed.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:31
Counter add(Counter LHS, Counter RHS)
Return a counter that represents the expression that adds LHS and RHS.
iterator_range< FunctionRecordIterator > getCoveredFunctions() const
Gets all of the functions covered by this profile.
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:134
unsigned getExpressionID() const
The execution count information starting at a point in a file.
StringRef filename(StringRef path)
Get filename.
Definition: Path.cpp:548
std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector< uint64_t > &Counts)
Fill Counts with the profile data for the given function name.
friend const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:240
Coverage mapping information for a single function.
void dump(const Counter &C, llvm::raw_ostream &OS) const
CounterKind getKind() const
A CodeRegion associates some code with a counter.
A Counter mapping context is used to connect the counters, expressions and the obtained counter value...
unsigned getCounterID() const
static ErrorOr< std::unique_ptr< BinaryCoverageReader > > create(std::unique_ptr< MemoryBuffer > &ObjectBuffer, StringRef Arch)
static ManagedStatic< _object_error_category > error_category
static ManagedStatic< CoverageMappingErrorCategoryType > ErrorCategory
Associates a source range with an execution count.
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:129
std::pair< unsigned, unsigned > startLoc() const
iterator erase(iterator I)
Definition: SmallVector.h:455
Counter subtract(Counter LHS, Counter RHS)
Return a counter that represents the expression that subtracts RHS from LHS.
CoverageData getCoverageForFile(StringRef Filename)
Get the coverage for a particular file.
Code coverage information for a single function.
bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:215
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, int64_t FileSize=-1)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:412
friend const_iterator begin(StringRef path)
Get begin iterator over path.
Definition: Path.cpp:232
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
static bool isExpansion(const CountedRegion &R, unsigned FileID)
An ExpansionRegion represents a file expansion region that associates a source range with the expansi...
A SkippedRegion represents a source range with code that was skipped by a preprocessor or similar mea...
static Optional< unsigned > findMainViewFileID(StringRef SourceFile, const FunctionRecord &Function)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:123
static StringRef getFuncNameWithoutPrefix(const CoverageMappingRecord &Record)
Get the function name from the record, removing the filename prefix if necessary. ...
The mapping of profile information to coverage data.
unsigned Line
The line where this segment begins.
CoverageData getCoverageForFunction(const FunctionRecord &Function)
Get the coverage for a particular function.
#define I(x, y, z)
Definition: MD5.cpp:54
std::vector< CountedRegion > CountedRegions
Regions in the function along with their counts.
std::string Name
Raw function name.
unsigned FileID
The abstract file this expansion covers.
aarch64 promote const
LLVM Value Representation.
Definition: Value.h:69
static const char * name
std::vector< std::string > Filenames
Associated files.
std::pair< unsigned, unsigned > endLoc() const
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:38
#define DEBUG(X)
Definition: Debug.h:92
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
Reader for the indexed binary instrprof format.
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:61
static Counter getExpression(unsigned ExpressionId)
Return the counter that corresponds to a specific addition counter expression.
std::vector< StringRef > getUniqueSourceFiles() const
Returns the list of files that are covered.
A Counter is an abstract value that describes how to compute the execution count for a region of code...
static Counter getCounter(unsigned CounterId)
Return the counter that corresponds to a specific profile counter.
const FunctionRecord & Function
Coverage for the expansion.
static ErrorOr< std::unique_ptr< IndexedInstrProfReader > > create(std::string Path)
Factory method to create an indexed reader.
bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:110
Coverage information for a macro expansion or #included file.