[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