diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Frontend/ASTUnit.h | 40 | ||||
-rw-r--r-- | clang/lib/Frontend/ASTUnit.cpp | 5 | ||||
-rw-r--r-- | clang/tools/CIndex/CIndex.cpp | 6 |
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( |