1*9a199699SDimitry Andric //===-- DataCollection.cpp --------------------------------------*- C++ -*-===//
2*9a199699SDimitry Andric //
3*9a199699SDimitry Andric //                     The LLVM Compiler Infrastructure
4*9a199699SDimitry Andric //
5*9a199699SDimitry Andric // This file is distributed under the University of Illinois Open Source
6*9a199699SDimitry Andric // License. See LICENSE.TXT for details.
7*9a199699SDimitry Andric //
8*9a199699SDimitry Andric //===----------------------------------------------------------------------===//
9*9a199699SDimitry Andric 
10*9a199699SDimitry Andric #include "clang/AST/DataCollection.h"
11*9a199699SDimitry Andric 
12*9a199699SDimitry Andric #include "clang/Lex/Lexer.h"
13*9a199699SDimitry Andric 
14*9a199699SDimitry Andric namespace clang {
15*9a199699SDimitry Andric namespace data_collection {
16*9a199699SDimitry Andric 
17*9a199699SDimitry Andric /// Prints the macro name that contains the given SourceLocation into the given
18*9a199699SDimitry Andric /// raw_string_ostream.
printMacroName(llvm::raw_string_ostream & MacroStack,ASTContext & Context,SourceLocation Loc)19*9a199699SDimitry Andric static void printMacroName(llvm::raw_string_ostream &MacroStack,
20*9a199699SDimitry Andric                            ASTContext &Context, SourceLocation Loc) {
21*9a199699SDimitry Andric   MacroStack << Lexer::getImmediateMacroName(Loc, Context.getSourceManager(),
22*9a199699SDimitry Andric                                              Context.getLangOpts());
23*9a199699SDimitry Andric 
24*9a199699SDimitry Andric   // Add an empty space at the end as a padding to prevent
25*9a199699SDimitry Andric   // that macro names concatenate to the names of other macros.
26*9a199699SDimitry Andric   MacroStack << " ";
27*9a199699SDimitry Andric }
28*9a199699SDimitry Andric 
29*9a199699SDimitry Andric /// Returns a string that represents all macro expansions that expanded into the
30*9a199699SDimitry Andric /// given SourceLocation.
31*9a199699SDimitry Andric ///
32*9a199699SDimitry Andric /// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations
33*9a199699SDimitry Andric /// A and B are expanded from the same macros in the same order.
getMacroStack(SourceLocation Loc,ASTContext & Context)34*9a199699SDimitry Andric std::string getMacroStack(SourceLocation Loc, ASTContext &Context) {
35*9a199699SDimitry Andric   std::string MacroStack;
36*9a199699SDimitry Andric   llvm::raw_string_ostream MacroStackStream(MacroStack);
37*9a199699SDimitry Andric   SourceManager &SM = Context.getSourceManager();
38*9a199699SDimitry Andric 
39*9a199699SDimitry Andric   // Iterate over all macros that expanded into the given SourceLocation.
40*9a199699SDimitry Andric   while (Loc.isMacroID()) {
41*9a199699SDimitry Andric     // Add the macro name to the stream.
42*9a199699SDimitry Andric     printMacroName(MacroStackStream, Context, Loc);
43*9a199699SDimitry Andric     Loc = SM.getImmediateMacroCallerLoc(Loc);
44*9a199699SDimitry Andric   }
45*9a199699SDimitry Andric   MacroStackStream.flush();
46*9a199699SDimitry Andric   return MacroStack;
47*9a199699SDimitry Andric }
48*9a199699SDimitry Andric 
49*9a199699SDimitry Andric } // end namespace data_collection
50*9a199699SDimitry Andric } // end namespace clang
51