[cfe-commits] r108913 - in /cfe/trunk: include/clang/Driver/CC1Options.td include/clang/Frontend/FrontendActions.h include/clang/Frontend/FrontendOptions.h include/clang/Lex/Lexer.h lib/Frontend/CompilerInvocation.cpp lib/Frontend/FrontendActions.cpp lib/Lex/Lexer.cpp test/Lexer/Inputs/ test/Lexer/Inputs/preamble.txt test/Lexer/preamble.c tools/driver/cc1_main.cpp
Douglas Gregor
dgregor at apple.com
Tue Jul 20 13:18:03 PDT 2010
Author: dgregor
Date: Tue Jul 20 15:18:03 2010
New Revision: 108913
URL: http://llvm.org/viewvc/llvm-project?rev=108913&view=rev
Log:
Introduce a new lexer function to compute the "preamble" of a file,
which is the part of the file that contains all of the initial
comments, includes, and preprocessor directives that occur before any
of the actual code. Added a new -print-preamble cc1 action that is
only used for testing.
Added:
cfe/trunk/test/Lexer/Inputs/
cfe/trunk/test/Lexer/Inputs/preamble.txt (with props)
cfe/trunk/test/Lexer/preamble.c (with props)
Modified:
cfe/trunk/include/clang/Driver/CC1Options.td
cfe/trunk/include/clang/Frontend/FrontendActions.h
cfe/trunk/include/clang/Frontend/FrontendOptions.h
cfe/trunk/include/clang/Lex/Lexer.h
cfe/trunk/lib/Frontend/CompilerInvocation.cpp
cfe/trunk/lib/Frontend/FrontendActions.cpp
cfe/trunk/lib/Lex/Lexer.cpp
cfe/trunk/tools/driver/cc1_main.cpp
Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=108913&r1=108912&r2=108913&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Tue Jul 20 15:18:03 2010
@@ -304,6 +304,9 @@
HelpText<"Apply fix-it advice creating a file with the given suffix">;
def parse_print_callbacks : Flag<"-parse-print-callbacks">,
HelpText<"Run parser and print each callback invoked">;
+def print_preamble : Flag<"-print-preamble">,
+ HelpText<"Print the \"preamble\" of a file, which is a candidate for implicit"
+ " precompiled headers.">;
def emit_html : Flag<"-emit-html">,
HelpText<"Output input source as HTML">;
def ast_print : Flag<"-ast-print">,
Modified: cfe/trunk/include/clang/Frontend/FrontendActions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendActions.h?rev=108913&r1=108912&r2=108913&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/FrontendActions.h (original)
+++ cfe/trunk/include/clang/Frontend/FrontendActions.h Tue Jul 20 15:18:03 2010
@@ -134,6 +134,16 @@
virtual bool hasCodeCompletionSupport() const;
};
+class PrintPreambleAction : public FrontendAction {
+protected:
+ void ExecuteAction();
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &, llvm::StringRef) {
+ return 0;
+ }
+
+ virtual bool usesPreprocessorOnly() const { return true; }
+};
+
//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//
@@ -174,7 +184,7 @@
virtual bool hasPCHSupport() const { return true; }
};
-
+
} // end namespace clang
#endif
Modified: cfe/trunk/include/clang/Frontend/FrontendOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendOptions.h?rev=108913&r1=108912&r2=108913&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/FrontendOptions.h (original)
+++ cfe/trunk/include/clang/Frontend/FrontendOptions.h Tue Jul 20 15:18:03 2010
@@ -44,6 +44,7 @@
ParseSyntaxOnly, ///< Parse and perform semantic analysis.
PluginAction, ///< Run a plugin action, \see ActionName.
PrintDeclContext, ///< Print DeclContext and their Decls.
+ PrintPreamble, ///< Print the "preamble" of the input file
PrintPreprocessedInput, ///< -E mode.
RewriteMacros, ///< Expand macros but not #includes.
RewriteObjC, ///< ObjC->C Rewriter.
Modified: cfe/trunk/include/clang/Lex/Lexer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Lexer.h?rev=108913&r1=108912&r2=108913&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Lexer.h (original)
+++ cfe/trunk/include/clang/Lex/Lexer.h Tue Jul 20 15:18:03 2010
@@ -219,6 +219,19 @@
const SourceManager &SM,
const LangOptions &LangOpts);
+ /// \brief Compute the preamble of the given file.
+ ///
+ /// The preamble of a file contains the initial comments, include directives,
+ /// and other preprocessor directives that occur before the code in this
+ /// particular file actually begins. The preamble of the main source file is
+ /// a potential prefix header.
+ ///
+ /// \param Buffer The memory buffer containing the file's contents.
+ ///
+ /// \returns The offset into the file where the preamble ends and the rest
+ /// of the file begins.
+ static unsigned ComputePreamble(const llvm::MemoryBuffer *Buffer);
+
//===--------------------------------------------------------------------===//
// Internal implementation interfaces.
private:
Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=108913&r1=108912&r2=108913&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Tue Jul 20 15:18:03 2010
@@ -331,6 +331,7 @@
case frontend::ParsePrintCallbacks: return "-parse-print-callbacks";
case frontend::ParseSyntaxOnly: return "-fsyntax-only";
case frontend::PrintDeclContext: return "-print-decl-contexts";
+ case frontend::PrintPreamble: return "-print-preamble";
case frontend::PrintPreprocessedInput: return "-E";
case frontend::RewriteMacros: return "-rewrite-macros";
case frontend::RewriteObjC: return "-rewrite-objc";
@@ -989,6 +990,8 @@
Opts.ProgramAction = frontend::ParseSyntaxOnly; break;
case OPT_print_decl_contexts:
Opts.ProgramAction = frontend::PrintDeclContext; break;
+ case OPT_print_preamble:
+ Opts.ProgramAction = frontend::PrintPreamble; break;
case OPT_E:
Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
case OPT_rewrite_macros:
Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=108913&r1=108912&r2=108913&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendActions.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendActions.cpp Tue Jul 20 15:18:03 2010
@@ -19,6 +19,7 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -192,3 +193,32 @@
DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
CI.getPreprocessorOutputOpts());
}
+
+void PrintPreambleAction::ExecuteAction() {
+ switch (getCurrentFileKind()) {
+ case IK_C:
+ case IK_CXX:
+ case IK_ObjC:
+ case IK_ObjCXX:
+ case IK_OpenCL:
+ break;
+
+ case IK_None:
+ case IK_Asm:
+ case IK_PreprocessedC:
+ case IK_PreprocessedCXX:
+ case IK_PreprocessedObjC:
+ case IK_PreprocessedObjCXX:
+ case IK_AST:
+ case IK_LLVM_IR:
+ // We can't do anything with these.
+ return;
+ }
+
+ llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getFile(getCurrentFile());
+ if (Buffer) {
+ unsigned Preamble = Lexer::ComputePreamble(Buffer);
+ llvm::outs().write(Buffer->getBufferStart(), Preamble);
+ delete Buffer;
+ }
+}
Modified: cfe/trunk/lib/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Lexer.cpp?rev=108913&r1=108912&r2=108913&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Lexer.cpp (original)
+++ cfe/trunk/lib/Lex/Lexer.cpp Tue Jul 20 15:18:03 2010
@@ -28,6 +28,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cctype>
@@ -247,6 +248,130 @@
return TheTok.getLength();
}
+namespace {
+ enum PreambleDirectiveKind {
+ PDK_Skipped,
+ PDK_StartIf,
+ PDK_EndIf,
+ PDK_Unknown
+ };
+}
+
+unsigned Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer) {
+ // Create a lexer starting at the beginning of the file. Note that we use a
+ // "fake" file source location at offset 1 so that the lexer will track our
+ // position within the file.
+ const unsigned StartOffset = 1;
+ SourceLocation StartLoc = SourceLocation::getFromRawEncoding(StartOffset);
+ LangOptions LangOpts;
+ Lexer TheLexer(StartLoc, LangOpts, Buffer->getBufferStart(),
+ Buffer->getBufferStart(), Buffer->getBufferEnd());
+
+ bool InPreprocessorDirective = false;
+ Token TheTok;
+ Token IfStartTok;
+ unsigned IfCount = 0;
+ do {
+ TheLexer.LexFromRawLexer(TheTok);
+
+ if (InPreprocessorDirective) {
+ // If we've hit the end of the file, we're done.
+ if (TheTok.getKind() == tok::eof) {
+ InPreprocessorDirective = false;
+ break;
+ }
+
+ // If we haven't hit the end of the preprocessor directive, skip this
+ // token.
+ if (!TheTok.isAtStartOfLine())
+ continue;
+
+ // We've passed the end of the preprocessor directive, and will look
+ // at this token again below.
+ InPreprocessorDirective = false;
+ }
+
+ // Comments are okay; skip over them.
+ if (TheTok.getKind() == tok::comment)
+ continue;
+
+ if (TheTok.isAtStartOfLine() && TheTok.getKind() == tok::hash) {
+ // This is the start of a preprocessor directive.
+ Token HashTok = TheTok;
+ InPreprocessorDirective = true;
+
+ // Figure out which direective this is. Since we're lexing raw tokens,
+ // we don't have an identifier table available. Instead, just look at
+ // the raw identifier to recognize and categorize preprocessor directives.
+ TheLexer.LexFromRawLexer(TheTok);
+ if (TheTok.getKind() == tok::identifier && !TheTok.needsCleaning()) {
+ const char *IdStart = Buffer->getBufferStart()
+ + TheTok.getLocation().getRawEncoding() - 1;
+ llvm::StringRef Keyword(IdStart, TheTok.getLength());
+ PreambleDirectiveKind PDK
+ = llvm::StringSwitch<PreambleDirectiveKind>(Keyword)
+ .Case("include", PDK_Skipped)
+ .Case("__include_macros", PDK_Skipped)
+ .Case("define", PDK_Skipped)
+ .Case("undef", PDK_Skipped)
+ .Case("line", PDK_Skipped)
+ .Case("error", PDK_Skipped)
+ .Case("pragma", PDK_Skipped)
+ .Case("import", PDK_Skipped)
+ .Case("include_next", PDK_Skipped)
+ .Case("warning", PDK_Skipped)
+ .Case("ident", PDK_Skipped)
+ .Case("sccs", PDK_Skipped)
+ .Case("assert", PDK_Skipped)
+ .Case("unassert", PDK_Skipped)
+ .Case("if", PDK_StartIf)
+ .Case("ifdef", PDK_StartIf)
+ .Case("ifndef", PDK_StartIf)
+ .Case("elif", PDK_Skipped)
+ .Case("else", PDK_Skipped)
+ .Case("endif", PDK_EndIf)
+ .Default(PDK_Unknown);
+
+ switch (PDK) {
+ case PDK_Skipped:
+ continue;
+
+ case PDK_StartIf:
+ if (IfCount == 0)
+ IfStartTok = HashTok;
+
+ ++IfCount;
+ continue;
+
+ case PDK_EndIf:
+ // Mismatched #endif. The preamble ends here.
+ if (IfCount == 0)
+ break;
+
+ --IfCount;
+ continue;
+
+ case PDK_Unknown:
+ // We don't know what this directive is; stop at the '#'.
+ break;
+ }
+ }
+
+ // We only end up here if we didn't recognize the preprocessor
+ // directive or it was one that can't occur in the preamble at this
+ // point. Roll back the current token to the location of the '#'.
+ InPreprocessorDirective = false;
+ TheTok = HashTok;
+ }
+
+ // We hit a token
+ break;
+ } while (true);
+
+ SourceLocation End = IfCount? IfStartTok.getLocation() : TheTok.getLocation();
+ return End.getRawEncoding() - StartLoc.getRawEncoding();
+}
+
//===----------------------------------------------------------------------===//
// Character information.
//===----------------------------------------------------------------------===//
Added: cfe/trunk/test/Lexer/Inputs/preamble.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/Inputs/preamble.txt?rev=108913&view=auto
==============================================================================
--- cfe/trunk/test/Lexer/Inputs/preamble.txt (added)
+++ cfe/trunk/test/Lexer/Inputs/preamble.txt Tue Jul 20 15:18:03 2010
@@ -0,0 +1,11 @@
+// Preamble detection test: see below for comments and test commands.
+
+#include <blah>
+#ifndef FOO
+#else
+#ifdef BAR
+#elif WIBBLE
+#endif
+#pragma unknown
+#endif
+
Propchange: cfe/trunk/test/Lexer/Inputs/preamble.txt
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/Lexer/Inputs/preamble.txt
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/Lexer/Inputs/preamble.txt
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: cfe/trunk/test/Lexer/preamble.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/preamble.c?rev=108913&view=auto
==============================================================================
--- cfe/trunk/test/Lexer/preamble.c (added)
+++ cfe/trunk/test/Lexer/preamble.c Tue Jul 20 15:18:03 2010
@@ -0,0 +1,25 @@
+// Preamble detection test: see below for comments and test commands.
+
+#include <blah>
+#ifndef FOO
+#else
+#ifdef BAR
+#elif WIBBLE
+#endif
+#pragma unknown
+#endif
+
+#ifdef WIBBLE
+#include "honk"
+#else
+int foo();
+#endif
+
+// This test checks for detection of the preamble of a file, which
+// includes all of the starting comments and #includes. Note that any
+// changes to the preamble part of this file must be mirrored in
+// Inputs/preamble.txt, since we diff against it.
+
+// RUN: %clang_cc1 -print-preamble %s > %t
+// RUN: diff %t %S/Inputs/preamble.txt
+
Propchange: cfe/trunk/test/Lexer/preamble.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/Lexer/preamble.c
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/Lexer/preamble.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/tools/driver/cc1_main.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/cc1_main.cpp?rev=108913&r1=108912&r2=108913&view=diff
==============================================================================
--- cfe/trunk/tools/driver/cc1_main.cpp (original)
+++ cfe/trunk/tools/driver/cc1_main.cpp Tue Jul 20 15:18:03 2010
@@ -102,6 +102,7 @@
}
case PrintDeclContext: return new DeclContextPrintAction();
+ case PrintPreamble: return new PrintPreambleAction();
case PrintPreprocessedInput: return new PrintPreprocessedAction();
case RewriteMacros: return new RewriteMacrosAction();
case RewriteObjC: return new RewriteObjCAction();
More information about the cfe-commits
mailing list