aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Lex/Preprocessor.cpp
diff options
context:
space:
mode:
authorZiqing Luo <ziqing@udel.edu>2023-02-08 14:06:37 -0800
committerZiqing Luo <ziqing@udel.edu>2023-02-08 14:12:03 -0800
commit829bcb06ec43ab4b56b95ff040ec9d36feeaf06a (patch)
tree6608c7c245a389295ba0591e5dbf84194314ce94 /clang/lib/Lex/Preprocessor.cpp
parenta1507668807e6108c12ffecf3740cb339b15018d (diff)
downloadllvm-829bcb06ec43ab4b56b95ff040ec9d36feeaf06a.zip
llvm-829bcb06ec43ab4b56b95ff040ec9d36feeaf06a.tar.gz
llvm-829bcb06ec43ab4b56b95ff040ec9d36feeaf06a.tar.bz2
[-Wunsafe-buffer-usage] Add unsafe buffer checking opt-out pragmas
Add a pair of clang pragmas: - `#pragma clang unsafe_buffer_usage begin` and - `#pragma clang unsafe_buffer_usage end`, which specify the start and end of an (unsafe buffer checking) opt-out region, respectively. Behaviors of opt-out regions conform to the following rules: - No nested nor overlapped opt-out regions are allowed. One cannot start an opt-out region with `... unsafe_buffer_usage begin` but never close it with `... unsafe_buffer_usage end`. Mis-use of the pragmas will be warned. - Warnings raised from unsafe buffer operations inside such an opt-out region will always be suppressed. This behavior CANNOT be changed by `clang diagnostic` pragmas or command-line flags. - Warnings raised from unsafe operations outside of such opt-out regions may be reported on declarations inside opt-out regions. These warnings are NOT suppressed. - An un-suppressed unsafe operation warning may be attached with notes. These notes are NOT suppressed as well regardless of whether they are in opt-out regions. The implementation maintains a separate sequence of location pairs representing opt-out regions in `Preprocessor`. The `UnsafeBufferUsage` analyzer reads the region sequence to check if an unsafe operation is in an opt-out region. If it is, discard the warning raised from the operation immediately. This is a re-land after I reverting it at 9aa00c8a306561c4e3ddb09058e66bae322a0769. The compilation error should be resolved. Reviewed by: NoQ Differential revision: https://reviews.llvm.org/D140179
Diffstat (limited to 'clang/lib/Lex/Preprocessor.cpp')
-rw-r--r--clang/lib/Lex/Preprocessor.cpp69
1 files changed, 69 insertions, 0 deletions
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index fe9adb5..924a7e6 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -1462,6 +1462,75 @@ void Preprocessor::emitFinalMacroWarning(const Token &Identifier,
Diag(*A.FinalAnnotationLoc, diag::note_pp_macro_annotation) << 2;
}
+bool Preprocessor::isSafeBufferOptOut(const SourceManager &SourceMgr,
+ const SourceLocation &Loc) const {
+ // Try to find a region in `SafeBufferOptOutMap` where `Loc` is in:
+ auto FirstRegionEndingAfterLoc = llvm::partition_point(
+ SafeBufferOptOutMap,
+ [&SourceMgr,
+ &Loc](const std::pair<SourceLocation, SourceLocation> &Region) {
+ return SourceMgr.isBeforeInTranslationUnit(Region.second, Loc);
+ });
+
+ if (FirstRegionEndingAfterLoc != SafeBufferOptOutMap.end()) {
+ // To test if the start location of the found region precedes `Loc`:
+ return SourceMgr.isBeforeInTranslationUnit(FirstRegionEndingAfterLoc->first,
+ Loc);
+ }
+ // If we do not find a region whose end location passes `Loc`, we want to
+ // check if the current region is still open:
+ if (!SafeBufferOptOutMap.empty() &&
+ SafeBufferOptOutMap.back().first == SafeBufferOptOutMap.back().second)
+ return SourceMgr.isBeforeInTranslationUnit(SafeBufferOptOutMap.back().first,
+ Loc);
+ return false;
+}
+
+bool Preprocessor::enterOrExitSafeBufferOptOutRegion(
+ bool isEnter, const SourceLocation &Loc) {
+ if (isEnter) {
+ if (isPPInSafeBufferOptOutRegion())
+ return true; // invalid enter action
+ InSafeBufferOptOutRegion = true;
+ CurrentSafeBufferOptOutStart = Loc;
+
+ // To set the start location of a new region:
+
+ if (!SafeBufferOptOutMap.empty()) {
+ auto *PrevRegion = &SafeBufferOptOutMap.back();
+ assert(PrevRegion->first != PrevRegion->second &&
+ "Shall not begin a safe buffer opt-out region before closing the "
+ "previous one.");
+ }
+ // If the start location equals to the end location, we call the region a
+ // open region or a unclosed region (i.e., end location has not been set
+ // yet).
+ SafeBufferOptOutMap.emplace_back(Loc, Loc);
+ } else {
+ if (!isPPInSafeBufferOptOutRegion())
+ return true; // invalid enter action
+ InSafeBufferOptOutRegion = false;
+
+ // To set the end location of the current open region:
+
+ assert(!SafeBufferOptOutMap.empty() &&
+ "Misordered safe buffer opt-out regions");
+ auto *CurrRegion = &SafeBufferOptOutMap.back();
+ assert(CurrRegion->first == CurrRegion->second &&
+ "Set end location to a closed safe buffer opt-out region");
+ CurrRegion->second = Loc;
+ }
+ return false;
+}
+
+bool Preprocessor::isPPInSafeBufferOptOutRegion() {
+ return InSafeBufferOptOutRegion;
+}
+bool Preprocessor::isPPInSafeBufferOptOutRegion(SourceLocation &StartLoc) {
+ StartLoc = CurrentSafeBufferOptOutStart;
+ return InSafeBufferOptOutRegion;
+}
+
ModuleLoader::~ModuleLoader() = default;
CommentHandler::~CommentHandler() = default;