A little hack to identify unwanted concurrency in CIndex
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97831 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 626a162..dca71cf 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -88,11 +88,49 @@
/// \brief Temporary files that should be removed when the ASTUnit is
/// destroyed.
llvm::SmallVector<llvm::sys::Path, 4> TemporaryFiles;
+
+#ifndef NDEBUG
+ /// \brief Simple hack to allow us to assert that ASTUnit is not being
+ /// used concurrently, which is not supported.
+ ///
+ /// Clients should create instances of the ConcurrencyCheck class whenever
+ /// using the ASTUnit in a way that isn't intended to be concurrent, which is
+ /// just about any usage.
+ unsigned int ConcurrencyCheckValue;
+ static const unsigned int CheckLocked = 28573289;
+ static const unsigned int CheckUnlocked = 9803453;
+#endif
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
-
+
public:
+ class ConcurrencyCheck {
+#ifndef NDEBUG
+ volatile ASTUnit &Self;
+#endif
+
+ public:
+ explicit ConcurrencyCheck(ASTUnit &Self)
+#ifndef NDEBUG
+ : Self(Self)
+#endif
+ {
+#ifndef NDEBUG
+ assert(Self.ConcurrencyCheckValue == CheckUnlocked &&
+ "Concurrent access to ASTUnit!");
+ Self.ConcurrencyCheckValue = CheckLocked;
+#endif
+ }
+
+#ifndef NDEBUG
+ ~ConcurrencyCheck() {
+ Self.ConcurrencyCheckValue = CheckUnlocked;
+ }
+#endif
+ };
+ friend class ConcurrencyCheck;
+
ASTUnit(bool MainFileIsAST);
~ASTUnit();
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index ef14df1..4ea1ccc 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -36,9 +36,12 @@
using namespace clang;
ASTUnit::ASTUnit(bool _MainFileIsAST)
- : MainFileIsAST(_MainFileIsAST) {
+ : MainFileIsAST(_MainFileIsAST), ConcurrencyCheckValue(CheckUnlocked) {
}
ASTUnit::~ASTUnit() {
+#ifndef NDEBUG
+ ConcurrencyCheckValue = CheckLocked;
+#endif
for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
TemporaryFiles[I].eraseFromDisk();
}
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 6fc7b53..de83547 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -1527,6 +1527,8 @@
ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
SourceLocation SLoc = cxloc::translateSourceLocation(Loc);
CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
if (SLoc.isValid()) {
@@ -2052,6 +2054,8 @@
if (!CXXUnit || !Tokens || !NumTokens)
return;
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
SourceRange R = cxloc::translateCXSourceRange(Range);
if (R.isInvalid())
return;
@@ -2175,6 +2179,8 @@
if (!CXXUnit || !Tokens)
return;
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
// Annotate all of the source locations in the region of interest that map
SourceRange RegionOfInterest;
RegionOfInterest.setBegin(