summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorVolodymyr Sapsai <vsapsai@apple.com>2018-12-07 20:29:54 +0000
committerVolodymyr Sapsai <vsapsai@apple.com>2018-12-07 20:29:54 +0000
commit978be4c1a360832fd90a03bb57441bf7de647c10 (patch)
treed7e9fd74ccbcab93d453385075655485dd8956ef /clang
parent03f9f15b16878e9a487429a39da6cb1934c27a15 (diff)
downloadbcm5719-llvm-978be4c1a360832fd90a03bb57441bf7de647c10.tar.gz
bcm5719-llvm-978be4c1a360832fd90a03bb57441bf7de647c10.zip
[Preprocessor] Don't avoid entering included files after hitting a fatal error.
Change in r337953 violated the contract for `CXTranslationUnit_KeepGoing`: > Do not stop processing when fatal errors are encountered. Use different approach to fix long processing times with multiple inclusion cycles. Instead of stopping preprocessing for fatal errors, do this after reaching the max allowed include depth and only for the files that were processed already. It is likely but not guaranteed those files cause a cycle. rdar://problem/46108547 Reviewers: erik.pilkington, arphaman Reviewed By: erik.pilkington Subscribers: jkorous, dexonsmith, ilya-biryukov, Dmitry.Kozhevnikov Differential Revision: https://reviews.llvm.org/D55095 llvm-svn: 348641
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Lex/Preprocessor.h4
-rw-r--r--clang/lib/Lex/PPDirectives.cpp10
-rw-r--r--clang/test/Index/Inputs/cycle.h1
-rw-r--r--clang/test/Index/keep-going-include-cycle.c10
-rw-r--r--clang/test/Index/keep-going.cpp11
5 files changed, 31 insertions, 5 deletions
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index 792f8af7dae..64ddb5307fb 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -319,6 +319,10 @@ class Preprocessor {
/// This is used when loading a precompiled preamble.
std::pair<int, bool> SkipMainFilePreamble;
+ /// Whether we hit an error due to reaching max allowed include depth. Allows
+ /// to avoid hitting the same error over and over again.
+ bool HasReachedMaxIncludeDepth = false;
+
public:
struct PreambleSkipInfo {
SourceLocation HashTokenLoc;
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 541dfecd657..a61ba736250 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -1707,6 +1707,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// Check that we don't have infinite #include recursion.
if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
Diag(FilenameTok, diag::err_pp_include_too_deep);
+ HasReachedMaxIncludeDepth = true;
return;
}
@@ -1855,10 +1856,11 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
if (PPOpts->SingleFileParseMode)
ShouldEnter = false;
- // Any diagnostics after the fatal error will not be visible. As the
- // compilation failed already and errors in subsequently included files won't
- // be visible, avoid preprocessing those files.
- if (ShouldEnter && Diags->hasFatalErrorOccurred())
+ // If we've reached the max allowed include depth, it is usually due to an
+ // include cycle. Don't enter already processed files again as it can lead to
+ // reaching the max allowed include depth again.
+ if (ShouldEnter && HasReachedMaxIncludeDepth && File &&
+ HeaderInfo.getFileInfo(File).NumIncludes)
ShouldEnter = false;
// Determine whether we should try to import the module for this #include, if
diff --git a/clang/test/Index/Inputs/cycle.h b/clang/test/Index/Inputs/cycle.h
new file mode 100644
index 00000000000..5dc8890f146
--- /dev/null
+++ b/clang/test/Index/Inputs/cycle.h
@@ -0,0 +1 @@
+#include "cycle.h"
diff --git a/clang/test/Index/keep-going-include-cycle.c b/clang/test/Index/keep-going-include-cycle.c
new file mode 100644
index 00000000000..b0fe24fa25d
--- /dev/null
+++ b/clang/test/Index/keep-going-include-cycle.c
@@ -0,0 +1,10 @@
+#include "cycle.h"
+#include "foo.h"
+
+// RUN: env CINDEXTEST_KEEP_GOING=1 c-index-test -test-print-type -I%S/Inputs %s 2> %t.stderr.txt | FileCheck %s
+// RUN: FileCheck -check-prefix CHECK-DIAG %s < %t.stderr.txt
+
+// Verify that we don't stop preprocessing after an include cycle.
+// CHECK: VarDecl=global_var:1:12 [type=int] [typekind=Int] [isPOD=1]
+
+// CHECK-DIAG: cycle.h:1:10: error: #include nested too deeply
diff --git a/clang/test/Index/keep-going.cpp b/clang/test/Index/keep-going.cpp
index dbfcad32d3d..b3f29c5d3da 100644
--- a/clang/test/Index/keep-going.cpp
+++ b/clang/test/Index/keep-going.cpp
@@ -9,11 +9,18 @@ class B : public A<int> { };
class C : public A<float> { };
-// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_KEEP_GOING=1 c-index-test -test-print-type %s -std=c++03 2> %t.stderr.txt | FileCheck %s
+// Not found includes shouldn't affect subsequent correct includes.
+#include "foo.h"
+
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_KEEP_GOING=1 c-index-test -test-print-type -I%S/Inputs %s -std=c++03 2> %t.stderr.txt | FileCheck %s
// RUN: FileCheck -check-prefix CHECK-DIAG %s < %t.stderr.txt
+// Verify that even without CINDEXTEST_EDITING we don't stop processing after a fatal error.
+// RUN: env CINDEXTEST_KEEP_GOING=1 c-index-test -test-print-type -I%S/Inputs %s -std=c++03 2> %t.stderr.txt | FileCheck -check-prefix CHECK-KEEP-GOING-ONLY %s
+
// CHECK: inclusion directive=missing1.h ((null)) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: inclusion directive=missing2.h ((null)) [type=] [typekind=Invalid] [isPOD=0]
+// CHECK: inclusion directive=foo.h ({{.*[/\\]}}test{{[/\\]}}Index{{[/\\]}}Inputs{{[/\\]}}foo.h) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: ClassTemplate=A:4:7 (Definition) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: TemplateTypeParameter=T:3:16 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
// CHECK: FieldDecl=a:4:13 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
@@ -25,5 +32,7 @@ class C : public A<float> { };
// CHECK: C++ base class specifier=A<float>:4:7 [access=public isVirtual=false] [type=A<float>] [typekind=Unexposed] [templateargs/1= [type=float] [typekind=Float]] [canonicaltype=A<float>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=float] [typekind=Float]] [isPOD=0] [nbFields=1]
// CHECK: TemplateRef=A:4:7 [type=] [typekind=Invalid] [isPOD=0]
+// CHECK-KEEP-GOING-ONLY: VarDecl=global_var:1:12 [type=int] [typekind=Int] [isPOD=1]
+
// CHECK-DIAG: keep-going.cpp:1:10: fatal error: 'missing1.h' file not found
// CHECK-DIAG: keep-going.cpp:8:10: fatal error: 'missing2.h' file not found
OpenPOWER on IntegriCloud