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(