[clang] 5767085 - Fix infinite recursion in deferred diag emitter
Yaxun Liu via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 1 19:20:56 PDT 2020
Author: Yaxun (Sam) Liu
Date: 2020-04-01T22:17:43-04:00
New Revision: 5767085c8de97d15d7fb5433f22bb5b858cc4f3a
URL: https://github.com/llvm/llvm-project/commit/5767085c8de97d15d7fb5433f22bb5b858cc4f3a
DIFF: https://github.com/llvm/llvm-project/commit/5767085c8de97d15d7fb5433f22bb5b858cc4f3a.diff
LOG: Fix infinite recursion in deferred diag emitter
Currently deferred diagnostic emitter checks variable decl in DeclRefExpr, which
causes infinite recursion for cases like long a = (long)&a;.
Deferred diagnostic emitter does not need check variable decls in DeclRefExpr
since reference of a variable does not cause emission of functions directly or
indirectly. Therefore there is no need to check variable decls in DeclRefExpr.
Differential Revision: https://reviews.llvm.org/D76937
Added:
Modified:
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaDecl.cpp
clang/test/OpenMP/nvptx_target_exceptions_messages.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 03475240f6f9..44b5115d9d2f 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1501,43 +1501,60 @@ class DeferredDiagnosticsEmitter
}
void visitUsedDecl(SourceLocation Loc, Decl *D) {
- if (auto *FD = dyn_cast<FunctionDecl>(D)) {
- FunctionDecl *Caller = UseStack.empty() ? nullptr : UseStack.back();
- auto IsKnownEmitted = S.getEmissionStatus(FD, /*Final=*/true) ==
- Sema::FunctionEmissionStatus::Emitted;
- if (!Caller)
- ShouldEmit = IsKnownEmitted;
- if ((!ShouldEmit && !S.getLangOpts().OpenMP && !Caller) ||
- S.shouldIgnoreInHostDeviceCheck(FD) || Visited.count(D))
- return;
- // Finalize analysis of OpenMP-specific constructs.
- if (Caller && S.LangOpts.OpenMP && UseStack.size() == 1)
- S.finalizeOpenMPDelayedAnalysis(Caller, FD, Loc);
- if (Caller)
- S.DeviceKnownEmittedFns[FD] = {Caller, Loc};
- if (ShouldEmit || InOMPDeviceContext)
- S.emitDeferredDiags(FD, Caller);
- Visited.insert(D);
- UseStack.push_back(FD);
- if (auto *S = FD->getBody()) {
- this->Visit(S);
- }
- UseStack.pop_back();
- Visited.erase(D);
- } else if (auto *VD = dyn_cast<VarDecl>(D)) {
- if (auto *Init = VD->getInit()) {
- auto DevTy = OMPDeclareTargetDeclAttr::getDeviceType(VD);
- bool IsDev = DevTy && (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost ||
- *DevTy == OMPDeclareTargetDeclAttr::DT_Any);
- if (IsDev)
- ++InOMPDeviceContext;
- this->Visit(Init);
- if (IsDev)
- --InOMPDeviceContext;
- }
- } else
+ if (isa<VarDecl>(D))
+ return;
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ checkFunc(Loc, FD);
+ else
Inherited::visitUsedDecl(Loc, D);
}
+
+ void checkVar(VarDecl *VD) {
+ assert(VD->isFileVarDecl() &&
+ "Should only check file-scope variables");
+ if (auto *Init = VD->getInit()) {
+ auto DevTy = OMPDeclareTargetDeclAttr::getDeviceType(VD);
+ bool IsDev = DevTy && (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost ||
+ *DevTy == OMPDeclareTargetDeclAttr::DT_Any);
+ if (IsDev)
+ ++InOMPDeviceContext;
+ this->Visit(Init);
+ if (IsDev)
+ --InOMPDeviceContext;
+ }
+ }
+
+ void checkFunc(SourceLocation Loc, FunctionDecl *FD) {
+ FunctionDecl *Caller = UseStack.empty() ? nullptr : UseStack.back();
+ auto IsKnownEmitted = S.getEmissionStatus(FD, /*Final=*/true) ==
+ Sema::FunctionEmissionStatus::Emitted;
+ if (!Caller)
+ ShouldEmit = IsKnownEmitted;
+ if ((!ShouldEmit && !S.getLangOpts().OpenMP && !Caller) ||
+ S.shouldIgnoreInHostDeviceCheck(FD) || Visited.count(FD))
+ return;
+ // Finalize analysis of OpenMP-specific constructs.
+ if (Caller && S.LangOpts.OpenMP && UseStack.size() == 1)
+ S.finalizeOpenMPDelayedAnalysis(Caller, FD, Loc);
+ if (Caller)
+ S.DeviceKnownEmittedFns[FD] = {Caller, Loc};
+ if (ShouldEmit || InOMPDeviceContext)
+ S.emitDeferredDiags(FD, Caller);
+ Visited.insert(FD);
+ UseStack.push_back(FD);
+ if (auto *S = FD->getBody()) {
+ this->Visit(S);
+ }
+ UseStack.pop_back();
+ Visited.erase(FD);
+ }
+
+ void checkRecordedDecl(Decl *D) {
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ checkFunc(SourceLocation(), FD);
+ else
+ checkVar(cast<VarDecl>(D));
+ }
};
} // namespace
@@ -1552,7 +1569,7 @@ void Sema::emitDeferredDiags() {
DeferredDiagnosticsEmitter DDE(*this);
for (auto D : DeclsToCheckForDeferredDiags)
- DDE.visitUsedDecl(SourceLocation(), D);
+ DDE.checkRecordedDecl(D);
}
// In CUDA, there are some constructs which may appear in semantically-valid
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ea3a0c22c401..494a1cd1a685 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12257,7 +12257,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
VDecl->setInitStyle(VarDecl::ListInit);
}
- if (LangOpts.OpenMP && VDecl->hasGlobalStorage())
+ if (LangOpts.OpenMP && VDecl->isFileVarDecl())
DeclsToCheckForDeferredDiags.push_back(VDecl);
CheckCompleteVariableDeclaration(VDecl);
}
diff --git a/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp b/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp
index faff77e0a43b..c71615d2521f 100644
--- a/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp
+++ b/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp
@@ -1,5 +1,10 @@
-// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -fexceptions -fcxx-exceptions
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fexceptions -fcxx-exceptions -ferror-limit 100
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown \
+// RUN: -verify=host -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc \
+// RUN: %s -o %t-ppc-host.bc -fexceptions -fcxx-exceptions
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown \
+// RUN: -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s \
+// RUN: -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - \
+// RUN: -fexceptions -fcxx-exceptions -ferror-limit 100
#ifndef HEADER
#define HEADER
@@ -81,4 +86,17 @@ int (*B)() = &foobar2;
int foobar1() { throw 1; }
int foobar2() { throw 1; } // expected-error {{cannot use 'throw' with exceptions disabled}}
+
+int foobar3();
+int (*C)() = &foobar3; // expected-warning {{declaration is not declared in any declare target region}}
+ // host-warning at -1 {{declaration is not declared in any declare target region}}
+#pragma omp declare target
+int (*D)() = C; // expected-note {{used here}}
+ // host-note at -1 {{used here}}
+#pragma omp end declare target
+int foobar3() { throw 1; }
+
+// Check no infinite recursion in deferred diagnostic emitter.
+long E = (long)&E;
+
#endif // HEADER
More information about the cfe-commits
mailing list