summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Mankov <evgeny.mankov@gmail.com>2019-08-27 22:15:32 +0000
committerEvgeny Mankov <evgeny.mankov@gmail.com>2019-08-27 22:15:32 +0000
commit2ed2e62498b7cccf951b7c671498625cecd2a862 (patch)
tree55eec008498bc42eae38b77d850d0c7e8a042a48
parent1fac68b0dc19b03fd2c5e9856f0f2c5a11691348 (diff)
downloadbcm5719-llvm-2ed2e62498b7cccf951b7c671498625cecd2a862.tar.gz
bcm5719-llvm-2ed2e62498b7cccf951b7c671498625cecd2a862.zip
[preprocessor] Add an opportunity to retain excluded conditional blocks
It is handy for clang tooling, for instance, in source to source transformation. Reviewers: vpykhtin (Valery Pykhtin), erichkeane (Erich Keane) Subscribers: rsmith (Richard Smith), akyrtzi (Argyrios Kyrtzidis) Tags: #clang Differential Revision: https://reviews.llvm.org/D66597 llvm-svn: 370123
-rw-r--r--clang/include/clang-c/Index.h7
-rw-r--r--clang/include/clang/Frontend/ASTUnit.h1
-rw-r--r--clang/include/clang/Lex/PreprocessorOptions.h4
-rw-r--r--clang/lib/Frontend/ASTUnit.cpp2
-rw-r--r--clang/lib/Lex/PPDirectives.cpp20
-rw-r--r--clang/test/Index/retain-excluded-conditional-blocks.m132
-rw-r--r--clang/tools/c-index-test/c-index-test.c30
-rw-r--r--clang/tools/libclang/CIndex.cpp4
8 files changed, 194 insertions, 6 deletions
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 74badac740b..bdce233ce8b 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -1356,7 +1356,12 @@ enum CXTranslationUnit_Flags {
* the case where these warnings are not of interest, as for an IDE for
* example, which typically shows only the diagnostics in the main file.
*/
- CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles = 0x4000
+ CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles = 0x4000,
+
+ /**
+ * Tells the preprocessor not to skip excluded conditional blocks.
+ */
+ CXTranslationUnit_RetainExcludedConditionalBlocks = 0x8000,
};
/**
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index 08cc91946eb..a36655150d4 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -832,6 +832,7 @@ public:
SkipFunctionBodiesScope::None,
bool SingleFileParse = false, bool UserFilesAreVolatile = false,
bool ForSerialization = false,
+ bool RetainExcludedConditionalBlocks = false,
llvm::Optional<StringRef> ModuleFormat = llvm::None,
std::unique_ptr<ASTUnit> *ErrAST = nullptr,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
diff --git a/clang/include/clang/Lex/PreprocessorOptions.h b/clang/include/clang/Lex/PreprocessorOptions.h
index 1480548c7fb..8824f0a51d0 100644
--- a/clang/include/clang/Lex/PreprocessorOptions.h
+++ b/clang/include/clang/Lex/PreprocessorOptions.h
@@ -142,6 +142,9 @@ public:
/// compiler invocation and its buffers will be reused.
bool RetainRemappedFileBuffers = false;
+ /// When enabled, excluded conditional blocks retain in the main file.
+ bool RetainExcludedConditionalBlocks = false;
+
/// The Objective-C++ ARC standard library that we should support,
/// by providing appropriate definitions to retrofit the standard library
/// with support for lifetime-qualified pointers.
@@ -201,6 +204,7 @@ public:
RetainRemappedFileBuffers = true;
PrecompiledPreambleBytes.first = 0;
PrecompiledPreambleBytes.second = false;
+ RetainExcludedConditionalBlocks = false;
}
};
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index ac6e6b6048e..35348ffe13b 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -1735,6 +1735,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies,
bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,
+ bool RetainExcludedConditionalBlocks,
llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
assert(Diags.get() && "no DiagnosticsEngine was provided");
@@ -1762,6 +1763,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
PPOpts.SingleFileParseMode = SingleFileParse;
+ PPOpts.RetainExcludedConditionalBlocks = RetainExcludedConditionalBlocks;
// Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 5eac1da115c..525f95b96e0 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -2855,6 +2855,9 @@ void Preprocessor::HandleIfdefDirective(Token &Result,
Callbacks->Ifdef(DirectiveTok.getLocation(), MacroNameTok, MD);
}
+ bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
+ getSourceManager().isInMainFile(DirectiveTok.getLocation());
+
// Should we include the stuff contained by this directive?
if (PPOpts->SingleFileParseMode && !MI) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
@@ -2862,7 +2865,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result,
CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
/*wasskip*/false, /*foundnonskip*/false,
/*foundelse*/false);
- } else if (!MI == isIfndef) {
+ } else if (!MI == isIfndef || RetainExcludedCB) {
// Yes, remember that we are inside a conditional, then lex the next token.
CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
/*wasskip*/false, /*foundnonskip*/true,
@@ -2903,13 +2906,16 @@ void Preprocessor::HandleIfDirective(Token &IfToken,
IfToken.getLocation(), DER.ExprRange,
(ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False));
+ bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
+ getSourceManager().isInMainFile(IfToken.getLocation());
+
// Should we include the stuff contained by this directive?
if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
// the directive blocks.
CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false,
/*foundnonskip*/false, /*foundelse*/false);
- } else if (ConditionalTrue) {
+ } else if (ConditionalTrue || RetainExcludedCB) {
// Yes, remember that we are inside a conditional, then lex the next token.
CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false,
/*foundnonskip*/true, /*foundelse*/false);
@@ -2971,7 +2977,10 @@ void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) {
if (Callbacks)
Callbacks->Else(Result.getLocation(), CI.IfLoc);
- if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) {
+ bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
+ getSourceManager().isInMainFile(Result.getLocation());
+
+ if ((PPOpts->SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
// the directive blocks.
CurPPLexer->pushConditionalLevel(CI.IfLoc, /*wasskip*/false,
@@ -3013,7 +3022,10 @@ void Preprocessor::HandleElifDirective(Token &ElifToken,
Callbacks->Elif(ElifToken.getLocation(), ConditionRange,
PPCallbacks::CVK_NotEvaluated, CI.IfLoc);
- if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) {
+ bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
+ getSourceManager().isInMainFile(ElifToken.getLocation());
+
+ if ((PPOpts->SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
// the directive blocks.
CurPPLexer->pushConditionalLevel(ElifToken.getLocation(), /*wasskip*/false,
diff --git a/clang/test/Index/retain-excluded-conditional-blocks.m b/clang/test/Index/retain-excluded-conditional-blocks.m
new file mode 100644
index 00000000000..ebfc7c5723d
--- /dev/null
+++ b/clang/test/Index/retain-excluded-conditional-blocks.m
@@ -0,0 +1,132 @@
+// RUN: c-index-test -retain-excluded-conditional-blocks %s | FileCheck %s
+
+#include <stdint.h>
+
+// CHECK: TypedefDecl=intptr_t
+
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=MyCls
+@interface MyCls
+// CHECK: [[@LINE+1]]:8: ObjCInstanceMethodDecl=some_meth
+-(void)some_meth;
+@end
+
+#if 1
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test1
+@interface Test1 @end
+#else
+// CHECK: [[@LINE+1]]:12:
+@interface Test2 @end
+#endif
+
+#if 0
+// CHECK: [[@LINE+1]]:12:
+@interface Test3 @end
+#else
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test4
+@interface Test4 @end
+#endif
+
+#if SOMETHING_NOT_DEFINED
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test5
+@interface Test5 @end
+#else
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test6
+@interface Test6 @end
+#endif
+
+#define SOMETHING_DEFINED 1
+#if SOMETHING_DEFINED
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test7
+@interface Test7 @end
+#else
+// CHECK: [[@LINE+1]]:12:
+@interface Test8 @end
+#endif
+
+#if defined(SOMETHING_NOT_DEFINED)
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test9
+@interface Test9 @end
+#else
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test10
+@interface Test10 @end
+#endif
+
+#if defined(SOMETHING_DEFINED)
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test11
+@interface Test11 @end
+#else
+// CHECK: [[@LINE+1]]:12:
+@interface Test12 @end
+#endif
+
+#if SOMETHING_NOT_DEFINED1
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test13
+@interface Test13 @end
+#elif SOMETHING_NOT_DEFINED2
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test14
+@interface Test14 @end
+#else
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test15
+@interface Test15 @end
+#endif
+
+#ifdef SOMETHING_NOT_DEFINED
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test19
+@interface Test19 @end
+#else
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test20
+@interface Test20 @end
+#endif
+
+#ifdef SOMETHING_DEFINED
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test21
+@interface Test21 @end
+#else
+// CHECK: [[@LINE+1]]:12:
+@interface Test22 @end
+#endif
+
+#ifndef SOMETHING_NOT_DEFINED
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test23
+@interface Test23 @end
+#else
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test24
+@interface Test24 @end
+#endif
+
+#ifndef SOMETHING_DEFINED
+// CHECK: [[@LINE+1]]:12:
+@interface Test25 @end
+#else
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test26
+@interface Test26 @end
+#endif
+
+#if 1 < SOMETHING_NOT_DEFINED
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test27
+@interface Test27 @end
+#else
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test28
+@interface Test28 @end
+#endif
+
+#if SOMETHING_NOT_DEFINED
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test29
+@interface Test29 @end
+#endif
+
+#ifdef SOMETHING_NOT_DEFINED
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test30
+@interface Test30 @end
+#endif
+
+#ifdef SOMETHING_DEFINED
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test31
+@interface Test31 @end
+#elif !defined(SOMETHING_NOT_DEFINED)
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test32
+@interface Test32 @end
+#else
+// CHECK: [[@LINE+1]]:12: ObjCInterfaceDecl=Test33
+@interface Test33 @end
+#endif
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index 33751714b84..dc7e449a207 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -2181,6 +2181,34 @@ static int perform_single_file_parse(const char *filename) {
return result;
}
+static int perform_file_retain_excluded_cb(const char *filename) {
+ CXIndex Idx;
+ CXTranslationUnit TU;
+ enum CXErrorCode Err;
+ int result;
+
+ Idx = clang_createIndex(/* excludeDeclsFromPCH */1,
+ /* displayDiagnostics=*/1);
+
+ Err = clang_parseTranslationUnit2(Idx, filename,
+ /*command_line_args=*/NULL,
+ /*num_command_line_args=*/0,
+ /*unsaved_files=*/NULL,
+ /*num_unsaved_files=*/0,
+ CXTranslationUnit_RetainExcludedConditionalBlocks, &TU);
+ if (Err != CXError_Success) {
+ fprintf(stderr, "Unable to load translation unit!\n");
+ describeLibclangFailure(Err);
+ clang_disposeIndex(Idx);
+ return 1;
+ }
+
+ result = perform_test_load(Idx, TU, /*filter=*/"all", /*prefix=*/NULL, FilteredPrintingVisitor, /*PostVisit=*/NULL,
+ /*CommentSchemaFile=*/NULL);
+ clang_disposeIndex(Idx);
+ return result;
+}
+
/******************************************************************************/
/* Logic for testing clang_getCursor(). */
/******************************************************************************/
@@ -4849,6 +4877,8 @@ int cindextest_main(int argc, const char **argv) {
}
else if (argc >= 3 && strcmp(argv[1], "-single-file-parse") == 0)
return perform_single_file_parse(argv[2]);
+ else if (argc >= 3 && strcmp(argv[1], "-retain-excluded-conditional-blocks") == 0)
+ return perform_file_retain_excluded_cb(argv[2]);
else if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0)
return perform_file_scan(argv[2], argv[3],
argc >= 5 ? argv[4] : 0);
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 344d6f36d1f..61b60e2bf88 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -3417,6 +3417,8 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename,
= options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
bool SingleFileParse = options & CXTranslationUnit_SingleFileParse;
bool ForSerialization = options & CXTranslationUnit_ForSerialization;
+ bool RetainExcludedCB = options &
+ CXTranslationUnit_RetainExcludedConditionalBlocks;
SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None;
if (options & CXTranslationUnit_SkipFunctionBodies) {
SkipFunctionBodies =
@@ -3517,7 +3519,7 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename,
/*RemappedFilesKeepOriginalName=*/true, PrecompilePreambleAfterNParses,
TUKind, CacheCodeCompletionResults, IncludeBriefCommentsInCodeCompletion,
/*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies, SingleFileParse,
- /*UserFilesAreVolatile=*/true, ForSerialization,
+ /*UserFilesAreVolatile=*/true, ForSerialization, RetainExcludedCB,
CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(),
&ErrUnit));
OpenPOWER on IntegriCloud