blob: f29e8f159d72ebd802f341faa5c266a950d8c68c [file] [log] [blame]
Daniel Dunbareef63e02011-02-02 15:41:17 +00001//===--- HeaderIncludes.cpp - Generate Header Includes --------------------===//
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#include "clang/Frontend/Utils.h"
11#include "clang/Basic/SourceManager.h"
12#include "clang/Lex/Preprocessor.h"
13/*
14#include "clang/Basic/Diagnostic.h"
15#include "clang/Frontend/PreprocessorOutputOptions.h"
16#include "clang/Lex/MacroInfo.h"
17#include "clang/Lex/PPCallbacks.h"
18#include "clang/Lex/Pragma.h"
19#include "clang/Lex/TokenConcatenation.h"
20#include "llvm/ADT/SmallString.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/Config/config.h"
24#include "llvm/Support/raw_ostream.h"
25#include <cstdio>
26*/
27using namespace clang;
28
29namespace {
30class HeaderIncludesCallback : public PPCallbacks {
31 SourceManager &SM;
32 unsigned CurrentIncludeDepth;
33 bool HasProcessedPredefines;
34
35public:
36 HeaderIncludesCallback(const Preprocessor *PP)
37 : SM(PP->getSourceManager()), CurrentIncludeDepth(0),
38 HasProcessedPredefines(false) {}
39
40 virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
41 SrcMgr::CharacteristicKind FileType);
42};
43}
44
45void clang::AttachHeaderIncludeGen(Preprocessor &PP) {
46 PP.addPPCallbacks(new HeaderIncludesCallback(&PP));
47}
48
49void HeaderIncludesCallback::FileChanged(SourceLocation Loc,
50 FileChangeReason Reason,
51 SrcMgr::CharacteristicKind NewFileType) {
52 // Unless we are exiting a #include, make sure to skip ahead to the line the
53 // #include directive was at.
54 PresumedLoc UserLoc = SM.getPresumedLoc(Loc);
55 if (UserLoc.isInvalid())
56 return;
57
58 // Adjust the current include depth.
59 if (Reason == PPCallbacks::EnterFile) {
60 ++CurrentIncludeDepth;
61 } else {
62 if (CurrentIncludeDepth)
63 --CurrentIncludeDepth;
64
65 // We track when we are done with the predefines by watching for the first
66 // place where we drop back to a nesting depth of 0.
67 if (CurrentIncludeDepth == 0 && !HasProcessedPredefines)
68 HasProcessedPredefines = true;
69 }
70
71 // Dump the header include information we are past the predefines buffer.
72 if (HasProcessedPredefines && Reason == PPCallbacks::EnterFile) {
73 // Write to a temporary string to avoid unnecessary flushing on errs().
74 llvm::SmallString<512> Filename(UserLoc.getFilename());
75 Lexer::Stringify(Filename);
76
77 llvm::SmallString<256> Msg;
78 for (unsigned i = 0; i != CurrentIncludeDepth; ++i)
79 Msg += '.';
80 Msg += ' ';
81 Msg += Filename;
82 Msg += '\n';
83
84 llvm::errs() << Msg;
85 }
86}
87