[cfe-commits] r130808 - in /cfe/trunk: include/clang-c/Index.h include/clang/Lex/HeaderSearch.h lib/Lex/HeaderSearch.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/Index/Inputs/guarded.h test/Index/Inputs/pragma-once.h test/Index/annotate-tokens-pp.c tools/c-index-test/c-index-test.c tools/libclang/CIndex.cpp tools/libclang/libclang.darwin.exports tools/libclang/libclang.exports
Douglas Gregor
dgregor at apple.com
Tue May 3 17:14:37 PDT 2011
Author: dgregor
Date: Tue May 3 19:14:37 2011
New Revision: 130808
URL: http://llvm.org/viewvc/llvm-project?rev=130808&view=rev
Log:
Introduce a new libclang API, clang_isFileMultipleIncludeGuarded(),
which determines whether a particular file is actually a header that
is intended to be guarded from multiple inclusions within the same
translation unit.
Added:
cfe/trunk/test/Index/Inputs/guarded.h (with props)
cfe/trunk/test/Index/Inputs/pragma-once.h (with props)
Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/include/clang/Lex/HeaderSearch.h
cfe/trunk/lib/Lex/HeaderSearch.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/test/Index/annotate-tokens-pp.c
cfe/trunk/tools/c-index-test/c-index-test.c
cfe/trunk/tools/libclang/CIndex.cpp
cfe/trunk/tools/libclang/libclang.darwin.exports
cfe/trunk/tools/libclang/libclang.exports
Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=130808&r1=130807&r2=130808&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Tue May 3 19:14:37 2011
@@ -222,6 +222,14 @@
CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
/**
+ * \brief Determine whether the given header is guarded against
+ * multiple inclusions, either with the conventional
+ * #ifndef/#define/#endif macro guards or with #pragma once.
+ */
+CINDEX_LINKAGE unsigned
+clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
+
+/**
* \brief Retrieve a file handle within the given translation unit.
*
* \param tu the translation unit
Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearch.h?rev=130808&r1=130807&r2=130808&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearch.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderSearch.h Tue May 3 19:14:37 2011
@@ -31,6 +31,9 @@
/// isImport - True if this is a #import'd or #pragma once file.
unsigned isImport : 1;
+ /// isPragmaOnce - True if this is #pragma once file.
+ unsigned isPragmaOnce : 1;
+
/// DirInfo - Keep track of whether this is a system header, and if so,
/// whether it is C++ clean or not. This can be set by the include paths or
/// by #pragma gcc system_header. This is an instance of
@@ -66,8 +69,8 @@
const IdentifierInfo *ControllingMacro;
HeaderFileInfo()
- : isImport(false), DirInfo(SrcMgr::C_User), External(false),
- Resolved(false), NumIncludes(0), ControllingMacroID(0),
+ : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
+ External(false), Resolved(false), NumIncludes(0), ControllingMacroID(0),
ControllingMacro(0) {}
/// \brief Retrieve the controlling macro for this header file, if
@@ -77,7 +80,8 @@
/// \brief Determine whether this is a non-default header file info, e.g.,
/// it corresponds to an actual header we've included or tried to include.
bool isNonDefault() const {
- return isImport || NumIncludes || ControllingMacro || ControllingMacroID;
+ return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
+ ControllingMacroID;
}
};
@@ -242,7 +246,9 @@
/// MarkFileIncludeOnce - Mark the specified file as a "once only" file, e.g.
/// due to #pragma once.
void MarkFileIncludeOnce(const FileEntry *File) {
- getFileInfo(File).isImport = true;
+ HeaderFileInfo &FI = getFileInfo(File);
+ FI.isImport = true;
+ FI.isPragmaOnce = true;
}
/// MarkFileSystemHeader - Mark the specified file as a system header, e.g.
@@ -265,6 +271,13 @@
getFileInfo(File).ControllingMacro = ControllingMacro;
}
+ /// \brief Determine whether this file is intended to be safe from
+ /// multiple inclusions, e.g., it has #pragma once or a controlling
+ /// macro.
+ ///
+ /// This routine does not consider the effect of #import
+ bool isFileMultipleIncludeGuarded(const FileEntry *File);
+
/// CreateHeaderMap - This method returns a HeaderMap for the specified
/// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
const HeaderMap *CreateHeaderMap(const FileEntry *FE);
Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=130808&r1=130807&r2=130808&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
+++ cfe/trunk/lib/Lex/HeaderSearch.cpp Tue May 3 19:14:37 2011
@@ -482,6 +482,21 @@
return HFI;
}
+bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) {
+ // Check if we've ever seen this file as a header.
+ if (File->getUID() >= FileInfo.size())
+ return false;
+
+ // Resolve header file info from the external source, if needed.
+ HeaderFileInfo &HFI = FileInfo[File->getUID()];
+ if (ExternalSource && !HFI.Resolved) {
+ HFI = ExternalSource->GetHeaderFileInfo(File);
+ HFI.Resolved = true;
+ }
+
+ return HFI.isPragmaOnce || HFI.ControllingMacro || HFI.ControllingMacroID;
+}
+
void HeaderSearch::setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID) {
if (UID >= FileInfo.size())
FileInfo.resize(UID+1);
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=130808&r1=130807&r2=130808&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue May 3 19:14:37 2011
@@ -1697,7 +1697,8 @@
using namespace clang::io;
HeaderFileInfo HFI;
unsigned Flags = *d++;
- HFI.isImport = (Flags >> 3) & 0x01;
+ HFI.isImport = (Flags >> 4) & 0x01;
+ HFI.isPragmaOnce = (Flags >> 3) & 0x01;
HFI.DirInfo = (Flags >> 1) & 0x03;
HFI.Resolved = Flags & 0x01;
HFI.NumIncludes = ReadUnalignedLE16(d);
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=130808&r1=130807&r2=130808&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue May 3 19:14:37 2011
@@ -1280,7 +1280,8 @@
using namespace clang::io;
uint64_t Start = Out.tell(); (void)Start;
- unsigned char Flags = (Data.isImport << 3)
+ unsigned char Flags = (Data.isImport << 4)
+ | (Data.isPragmaOnce << 3)
| (Data.DirInfo << 1)
| Data.Resolved;
Emit8(Out, (uint8_t)Flags);
Added: cfe/trunk/test/Index/Inputs/guarded.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/Inputs/guarded.h?rev=130808&view=auto
==============================================================================
--- cfe/trunk/test/Index/Inputs/guarded.h (added)
+++ cfe/trunk/test/Index/Inputs/guarded.h Tue May 3 19:14:37 2011
@@ -0,0 +1,6 @@
+#ifndef GUARDED_HEADER_H
+#define GUARDED_HEADER_H
+
+int y;
+
+#endif // GUARDED_HEADER_H
Propchange: cfe/trunk/test/Index/Inputs/guarded.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/Index/Inputs/guarded.h
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/Index/Inputs/guarded.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: cfe/trunk/test/Index/Inputs/pragma-once.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/Inputs/pragma-once.h?rev=130808&view=auto
==============================================================================
--- cfe/trunk/test/Index/Inputs/pragma-once.h (added)
+++ cfe/trunk/test/Index/Inputs/pragma-once.h Tue May 3 19:14:37 2011
@@ -0,0 +1,3 @@
+#pragma once
+int i;
+
Propchange: cfe/trunk/test/Index/Inputs/pragma-once.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/Index/Inputs/pragma-once.h
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/Index/Inputs/pragma-once.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/test/Index/annotate-tokens-pp.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-tokens-pp.c?rev=130808&r1=130807&r2=130808&view=diff
==============================================================================
--- cfe/trunk/test/Index/annotate-tokens-pp.c (original)
+++ cfe/trunk/test/Index/annotate-tokens-pp.c Tue May 3 19:14:37 2011
@@ -25,7 +25,10 @@
fun_with_macro_bodies(x, { int z = x; ++z; });
}
-// RUN: c-index-test -test-annotate-tokens=%s:2:1:26:1 -I%S/Inputs %s | FileCheck %s
+#include "pragma-once.h"
+#include "guarded.h"
+
+// RUN: c-index-test -test-annotate-tokens=%s:2:1:30:1 -I%S/Inputs %s | FileCheck %s
// CHECK: Punctuation: "#" [2:1 - 2:2] preprocessing directive=
// CHECK: Identifier: "define" [2:2 - 2:8] preprocessing directive=
// CHECK: Identifier: "STILL_NOTHING" [2:9 - 2:22] macro definition=STILL_NOTHING
@@ -184,4 +187,5 @@
// CHECK: Punctuation: ")" [25:47 - 25:48] UnexposedStmt=
// CHECK: Punctuation: ";" [25:48 - 25:49] UnexposedStmt=
// CHECK: Punctuation: "}" [26:1 - 26:2] UnexposedStmt=
-
+// CHECK: {{28:1.*inclusion directive=pragma-once.h.*multi-include guarded}}
+// CHECK: {{29:1.*inclusion directive=guarded.h.*multi-include guarded}}
Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=130808&r1=130807&r2=130808&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Tue May 3 19:14:37 2011
@@ -158,7 +158,7 @@
int want_display_name = 0;
-static void PrintCursor(CXCursor Cursor) {
+static void PrintCursor(CXTranslationUnit TU, CXCursor Cursor) {
if (clang_isInvalid(Cursor.kind)) {
CXString ks = clang_getCursorKindSpelling(Cursor.kind);
printf("Invalid Cursor => %s", clang_getCString(ks));
@@ -277,6 +277,9 @@
CXString Included = clang_getFileName(File);
printf(" (%s)", clang_getCString(Included));
clang_disposeString(Included);
+
+ if (clang_isFileMultipleIncludeGuarded(TU, File))
+ printf(" [multi-include guarded]");
}
}
}
@@ -426,7 +429,7 @@
clang_getSpellingLocation(Loc, 0, &line, &column, 0);
printf("// %s: %s:%d:%d: ", FileCheckPrefix,
GetCursorSource(Cursor), line, column);
- PrintCursor(Cursor);
+ PrintCursor(Data->TU, Cursor);
PrintCursorExtent(Cursor);
printf("\n");
return CXChildVisit_Recurse;
@@ -479,7 +482,7 @@
} else if (Ref.kind != CXCursor_FunctionDecl) {
printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref),
curLine, curColumn);
- PrintCursor(Ref);
+ PrintCursor(Data->TU, Ref);
printf("\n");
}
}
@@ -554,6 +557,8 @@
CXClientData d) {
const char *linkage = 0;
+ VisitorData *Data = (VisitorData *)d;
+
if (clang_isInvalid(clang_getCursorKind(cursor)))
return CXChildVisit_Recurse;
@@ -566,7 +571,7 @@
}
if (linkage) {
- PrintCursor(cursor);
+ PrintCursor(Data->TU, cursor);
printf("linkage=%s\n", linkage);
}
@@ -579,11 +584,12 @@
static enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p,
CXClientData d) {
+ VisitorData *Data = (VisitorData *)d;
if (!clang_isInvalid(clang_getCursorKind(cursor))) {
CXType T = clang_getCursorType(cursor);
CXString S = clang_getTypeKindSpelling(T.kind);
- PrintCursor(cursor);
+ PrintCursor(Data->TU, cursor);
printf(" typekind=%s", clang_getCString(S));
if (clang_isConstQualifiedType(T))
printf(" const");
@@ -778,7 +784,7 @@
/* Logic for testing clang_getCursor(). */
/******************************************************************************/
-static void print_cursor_file_scan(CXCursor cursor,
+static void print_cursor_file_scan(CXTranslationUnit TU, CXCursor cursor,
unsigned start_line, unsigned start_col,
unsigned end_line, unsigned end_col,
const char *prefix) {
@@ -787,7 +793,7 @@
printf("-%s", prefix);
PrintExtent(stdout, start_line, start_col, end_line, end_col);
printf(" ");
- PrintCursor(cursor);
+ PrintCursor(TU, cursor);
printf("\n");
}
@@ -832,7 +838,7 @@
cursor = clang_getCursor(TU, clang_getLocation(TU, file, line, col));
if ((c == EOF || !clang_equalCursors(cursor, prevCursor)) &&
prevCursor.kind != CXCursor_InvalidFile) {
- print_cursor_file_scan(prevCursor, start_line, start_col,
+ print_cursor_file_scan(TU, prevCursor, start_line, start_col,
line, col, prefix);
start_line = line;
start_col = col;
@@ -1183,7 +1189,7 @@
clang_getLocation(TU, file, Locations[Loc].line,
Locations[Loc].column));
if (I + 1 == Repeats) {
- PrintCursor(Cursor);
+ PrintCursor(TU, Cursor);
printf("\n");
free(Locations[Loc].filename);
}
@@ -1287,7 +1293,7 @@
PrintExtent(stdout, start_line, start_column, end_line, end_column);
if (!clang_isInvalid(cursors[i].kind)) {
printf(" ");
- PrintCursor(cursors[i]);
+ PrintCursor(TU, cursors[i]);
}
printf("\n");
}
Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=130808&r1=130807&r2=130808&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue May 3 19:14:37 2011
@@ -30,6 +30,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/STLExtras.h"
@@ -2890,6 +2891,16 @@
return const_cast<FileEntry *>(FMgr.getFile(file_name));
}
+unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file) {
+ if (!tu || !file)
+ return 0;
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
+ FileEntry *FEnt = static_cast<FileEntry *>(file);
+ return CXXUnit->getPreprocessor().getHeaderSearchInfo()
+ .isFileMultipleIncludeGuarded(FEnt);
+}
+
} // end: extern "C"
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/tools/libclang/libclang.darwin.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.darwin.exports?rev=130808&r1=130807&r2=130808&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.darwin.exports (original)
+++ cfe/trunk/tools/libclang/libclang.darwin.exports Tue May 3 19:14:37 2011
@@ -115,6 +115,7 @@
_clang_isCursorDefinition
_clang_isDeclaration
_clang_isExpression
+_clang_isFileMultipleIncludeGuarded
_clang_isInvalid
_clang_isPODType
_clang_isPreprocessing
Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=130808&r1=130807&r2=130808&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Tue May 3 19:14:37 2011
@@ -115,6 +115,7 @@
clang_isCursorDefinition
clang_isDeclaration
clang_isExpression
+clang_isFileMultipleIncludeGuarded
clang_isInvalid
clang_isPODType
clang_isPreprocessing
More information about the cfe-commits
mailing list