 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
100.0% |
8 / 8 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
100.0% |
8 / 8 |
| |
|
Line Coverage: |
100.0% |
29 / 29 |
| |
 |
|
 |
1 : //===--- MultipleIncludeOpt.h - Header Multiple-Include Optzn ---*- 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 defines the MultipleIncludeOpt interface.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H
15 : #define LLVM_CLANG_MULTIPLEINCLUDEOPT_H
16 :
17 : namespace clang {
18 : class IdentifierInfo;
19 :
20 : /// MultipleIncludeOpt - This class implements the simple state machine that the
21 : /// Lexer class uses to detect files subject to the 'multiple-include'
22 : /// optimization. The public methods in this class are triggered by various
23 : /// events that occur when a file is lexed, and after the entire file is lexed,
24 : /// information about which macro (if any) controls the header is returned.
25 : class MultipleIncludeOpt {
26 : /// ReadAnyTokens - This is set to false when a file is first opened and true
27 : /// any time a token is returned to the client or a (non-multiple-include)
28 : /// directive is parsed. When the final #endif is parsed this is reset back
29 : /// to false, that way any tokens before the first #ifdef or after the last
30 : /// #endif can be easily detected.
31 : bool ReadAnyTokens;
32 :
33 : /// ReadAnyTokens - This is set to false when a file is first opened and true
34 : /// any time a token is returned to the client or a (non-multiple-include)
35 : /// directive is parsed. When the final #endif is parsed this is reset back
36 : /// to false, that way any tokens before the first #ifdef or after the last
37 : /// #endif can be easily detected.
38 : bool DidMacroExpansion;
39 :
40 : /// TheMacro - The controlling macro for a file, if valid.
41 : ///
42 : const IdentifierInfo *TheMacro;
43 : public:
44 144591: MultipleIncludeOpt() {
45 144591: ReadAnyTokens = false;
46 144591: DidMacroExpansion = false;
47 144591: TheMacro = 0;
48 144591: }
49 :
50 : /// Invalidate - Permenantly mark this file as not being suitable for the
51 : /// include-file optimization.
52 908: void Invalidate() {
53 : // If we have read tokens but have no controlling macro, the state-machine
54 : // below can never "accept".
55 908: ReadAnyTokens = true;
56 908: TheMacro = 0;
57 908: }
58 :
59 : /// getHasReadAnyTokensVal - This is used for the #ifndef hande-shake at the
60 : /// top of the file when reading preprocessor directives. Otherwise, reading
61 : /// the "ifndef x" would count as reading tokens.
62 288096: bool getHasReadAnyTokensVal() const { return ReadAnyTokens; }
63 :
64 : // If a token is read, remember that we have seen a side-effect in this file.
65 2394946: void ReadToken() { ReadAnyTokens = true; }
66 :
67 : /// ExpandedMacro - When a macro is expanded with this lexer as the current
68 : /// buffer, this method is called to disable the MIOpt if needed.
69 6809: void ExpandedMacro() { DidMacroExpansion = true; }
70 :
71 : /// EnterTopLevelIFNDEF - When entering a top-level #ifndef directive (or the
72 : /// "#if !defined" equivalent) without any preceding tokens, this method is
73 : /// called.
74 : ///
75 : /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller
76 : /// ensures that this is only called if there are no tokens read before the
77 : /// #ifndef. The caller is required to do this, because reading the #if line
78 : /// obviously reads in in tokens.
79 356: void EnterTopLevelIFNDEF(const IdentifierInfo *M) {
80 : // If the macro is already set, this is after the top-level #endif.
5: branch 0 taken
351: branch 1 taken
81 356: if (TheMacro)
82 5: return Invalidate();
83 :
84 : // If we have already expanded a macro by the end of the #ifndef line, then
85 : // there is a macro expansion *in* the #ifndef line. This means that the
86 : // condition could evaluate differently when subsequently #included. Reject
87 : // this.
1: branch 0 taken
350: branch 1 taken
88 351: if (DidMacroExpansion)
89 1: return Invalidate();
90 :
91 : // Remember that we're in the #if and that we have the macro.
92 350: ReadAnyTokens = true;
93 350: TheMacro = M;
94 : }
95 :
96 : /// EnterTopLevelConditional - This is invoked when a top level conditional
97 : /// (except #ifndef) is found.
98 615: void EnterTopLevelConditional() {
99 : /// If a conditional directive (except #ifndef) is found at the top level,
100 : /// there is a chunk of the file not guarded by the controlling macro.
101 615: Invalidate();
102 615: }
103 :
104 : /// ExitTopLevelConditional - This method is called when the lexer exits the
105 : /// top-level conditional.
106 590: void ExitTopLevelConditional() {
107 : // If we have a macro, that means the top of the file was ok. Set our state
108 : // back to "not having read any tokens" so we can detect anything after the
109 : // #endif.
287: branch 0 taken
303: branch 1 taken
110 590: if (!TheMacro) return Invalidate();
111 :
112 : // At this point, we haven't "read any tokens" but we do have a controlling
113 : // macro.
114 303: ReadAnyTokens = false;
115 : }
116 :
117 : /// GetControllingMacroAtEndOfFile - Once the entire file has been lexed, if
118 : /// there is a controlling macro, return it.
119 5618: const IdentifierInfo *GetControllingMacroAtEndOfFile() const {
120 : // If we haven't read any tokens after the #endif, return the controlling
121 : // macro if it's valid (if it isn't, it will be null).
412: branch 0 taken
5206: branch 1 taken
122 5618: if (!ReadAnyTokens)
123 412: return TheMacro;
124 5206: return 0;
125 : }
126 : };
127 :
128 : } // end namespace clang
129 :
130 : #endif
Generated: 2010-02-10 01:31 by zcov