|
58 | 58 | #include "llvm/ADT/SmallString.h"
|
59 | 59 | #include "llvm/ADT/SmallVector.h"
|
60 | 60 | #include "llvm/ADT/StringRef.h"
|
| 61 | +#include "llvm/ADT/iterator_range.h" |
61 | 62 | #include "llvm/Support/Capacity.h"
|
62 | 63 | #include "llvm/Support/ErrorHandling.h"
|
63 | 64 | #include "llvm/Support/MemoryBuffer.h"
|
@@ -1483,26 +1484,56 @@ void Preprocessor::emitFinalMacroWarning(const Token &Identifier,
|
1483 | 1484 | }
|
1484 | 1485 |
|
1485 | 1486 | bool Preprocessor::isSafeBufferOptOut(const SourceManager &SourceMgr,
|
1486 |
| - const SourceLocation &Loc) const { |
1487 |
| - // Try to find a region in `SafeBufferOptOutMap` where `Loc` is in: |
1488 |
| - auto FirstRegionEndingAfterLoc = llvm::partition_point( |
1489 |
| - SafeBufferOptOutMap, |
1490 |
| - [&SourceMgr, |
1491 |
| - &Loc](const std::pair<SourceLocation, SourceLocation> &Region) { |
1492 |
| - return SourceMgr.isBeforeInTranslationUnit(Region.second, Loc); |
1493 |
| - }); |
| 1487 | + const SourceLocation &Loc) const { |
| 1488 | + // The lambda that tests if a `Loc` is in an opt-out region given one opt-out |
| 1489 | + // region map: |
| 1490 | + auto TestInMap = [&SourceMgr](const SafeBufferOptOutRegionsTy &Map, |
| 1491 | + const SourceLocation &Loc) -> bool { |
| 1492 | + // Try to find a region in `SafeBufferOptOutMap` where `Loc` is in: |
| 1493 | + auto FirstRegionEndingAfterLoc = llvm::partition_point( |
| 1494 | + Map, [&SourceMgr, |
| 1495 | + &Loc](const std::pair<SourceLocation, SourceLocation> &Region) { |
| 1496 | + return SourceMgr.isBeforeInTranslationUnit(Region.second, Loc); |
| 1497 | + }); |
| 1498 | + |
| 1499 | + if (FirstRegionEndingAfterLoc != Map.end()) { |
| 1500 | + // To test if the start location of the found region precedes `Loc`: |
| 1501 | + return SourceMgr.isBeforeInTranslationUnit( |
| 1502 | + FirstRegionEndingAfterLoc->first, Loc); |
| 1503 | + } |
| 1504 | + // If we do not find a region whose end location passes `Loc`, we want to |
| 1505 | + // check if the current region is still open: |
| 1506 | + if (!Map.empty() && Map.back().first == Map.back().second) |
| 1507 | + return SourceMgr.isBeforeInTranslationUnit(Map.back().first, Loc); |
| 1508 | + return false; |
| 1509 | + }; |
1494 | 1510 |
|
1495 |
| - if (FirstRegionEndingAfterLoc != SafeBufferOptOutMap.end()) { |
1496 |
| - // To test if the start location of the found region precedes `Loc`: |
1497 |
| - return SourceMgr.isBeforeInTranslationUnit(FirstRegionEndingAfterLoc->first, |
1498 |
| - Loc); |
1499 |
| - } |
1500 |
| - // If we do not find a region whose end location passes `Loc`, we want to |
1501 |
| - // check if the current region is still open: |
1502 |
| - if (!SafeBufferOptOutMap.empty() && |
1503 |
| - SafeBufferOptOutMap.back().first == SafeBufferOptOutMap.back().second) |
1504 |
| - return SourceMgr.isBeforeInTranslationUnit(SafeBufferOptOutMap.back().first, |
1505 |
| - Loc); |
| 1511 | + // What the following does: |
| 1512 | + // |
| 1513 | + // If `Loc` belongs to the local TU, we just look up `SafeBufferOptOutMap`. |
| 1514 | + // Otherwise, `Loc` is from a loaded AST. We look up the |
| 1515 | + // `LoadedSafeBufferOptOutMap` first to get the opt-out region map of the |
| 1516 | + // loaded AST where `Loc` is at. Then we find if `Loc` is in an opt-out |
| 1517 | + // region w.r.t. the region map. If the region map is absent, it means there |
| 1518 | + // is no opt-out pragma in that loaded AST. |
| 1519 | + // |
| 1520 | + // Opt-out pragmas in the local TU or a loaded AST is not visible to another |
| 1521 | + // one of them. That means if you put the pragmas around a `#include |
| 1522 | + // "module.h"`, where module.h is a module, it is not actually suppressing |
| 1523 | + // warnings in module.h. This is fine because warnings in module.h will be |
| 1524 | + // reported when module.h is compiled in isolation and nothing in module.h |
| 1525 | + // will be analyzed ever again. So you will not see warnings from the file |
| 1526 | + // that imports module.h anyway. And you can't even do the same thing for PCHs |
| 1527 | + // because they can only be included from the command line. |
| 1528 | + |
| 1529 | + if (SourceMgr.isLocalSourceLocation(Loc)) |
| 1530 | + return TestInMap(SafeBufferOptOutMap, Loc); |
| 1531 | + |
| 1532 | + const SafeBufferOptOutRegionsTy *LoadedRegions = |
| 1533 | + LoadedSafeBufferOptOutMap.lookupLoadedOptOutMap(Loc, SourceMgr); |
| 1534 | + |
| 1535 | + if (LoadedRegions) |
| 1536 | + return TestInMap(*LoadedRegions, Loc); |
1506 | 1537 | return false;
|
1507 | 1538 | }
|
1508 | 1539 |
|
@@ -1551,6 +1582,47 @@ bool Preprocessor::isPPInSafeBufferOptOutRegion(SourceLocation &StartLoc) {
|
1551 | 1582 | return InSafeBufferOptOutRegion;
|
1552 | 1583 | }
|
1553 | 1584 |
|
| 1585 | +SmallVector<SourceLocation, 64> |
| 1586 | +Preprocessor::serializeSafeBufferOptOutMap() const { |
| 1587 | + assert(!InSafeBufferOptOutRegion && |
| 1588 | + "Attempt to serialize safe buffer opt-out regions before file being " |
| 1589 | + "completely preprocessed"); |
| 1590 | + |
| 1591 | + SmallVector<SourceLocation, 64> SrcSeq; |
| 1592 | + |
| 1593 | + for (const auto &[begin, end] : SafeBufferOptOutMap) { |
| 1594 | + SrcSeq.push_back(begin); |
| 1595 | + SrcSeq.push_back(end); |
| 1596 | + } |
| 1597 | + // Only `SafeBufferOptOutMap` gets serialized. No need to serialize |
| 1598 | + // `LoadedSafeBufferOptOutMap` because if this TU loads a pch/module, every |
| 1599 | + // pch/module in the pch-chain/module-DAG will be loaded one by one in order. |
| 1600 | + // It means that for each loading pch/module m, it just needs to load m's own |
| 1601 | + // `SafeBufferOptOutMap`. |
| 1602 | + return SrcSeq; |
| 1603 | +} |
| 1604 | + |
| 1605 | +bool Preprocessor::setDeserializedSafeBufferOptOutMap( |
| 1606 | + const SmallVectorImpl<SourceLocation> &SourceLocations) { |
| 1607 | + if (SourceLocations.size() == 0) |
| 1608 | + return false; |
| 1609 | + |
| 1610 | + assert(SourceLocations.size() % 2 == 0 && |
| 1611 | + "ill-formed SourceLocation sequence"); |
| 1612 | + |
| 1613 | + auto It = SourceLocations.begin(); |
| 1614 | + SafeBufferOptOutRegionsTy &Regions = |
| 1615 | + LoadedSafeBufferOptOutMap.findAndConsLoadedOptOutMap(*It, SourceMgr); |
| 1616 | + |
| 1617 | + do { |
| 1618 | + SourceLocation Begin = *It++; |
| 1619 | + SourceLocation End = *It++; |
| 1620 | + |
| 1621 | + Regions.emplace_back(Begin, End); |
| 1622 | + } while (It != SourceLocations.end()); |
| 1623 | + return true; |
| 1624 | +} |
| 1625 | + |
1554 | 1626 | ModuleLoader::~ModuleLoader() = default;
|
1555 | 1627 |
|
1556 | 1628 | CommentHandler::~CommentHandler() = default;
|
|
0 commit comments