summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Frontend/ASTUnit.h40
-rw-r--r--clang/lib/Frontend/ASTUnit.cpp5
-rw-r--r--clang/tools/CIndex/CIndex.cpp6
3 files changed, 49 insertions, 2 deletions
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index 626a162371b..dca71cffeca 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -88,11 +88,49 @@ class ASTUnit {
/// \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/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index ef14df10345..4ea1ccc943b 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/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/clang/tools/CIndex/CIndex.cpp b/clang/tools/CIndex/CIndex.cpp
index 6fc7b530307..de835475a65 100644
--- a/clang/tools/CIndex/CIndex.cpp
+++ b/clang/tools/CIndex/CIndex.cpp
@@ -1527,6 +1527,8 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
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 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
if (!CXXUnit || !Tokens || !NumTokens)
return;
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
SourceRange R = cxloc::translateCXSourceRange(Range);
if (R.isInvalid())
return;
@@ -2175,6 +2179,8 @@ void clang_annotateTokens(CXTranslationUnit TU,
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(
OpenPOWER on IntegriCloud