[cfe-dev] lower bound error searching for module preprocessing entities within a source range

Tom Honermann thonermann at coverity.com
Thu Sep 19 07:33:54 PDT 2013


Could someone please review/comment/commit this patch?

Tom.

On 08/28/2013 06:19 PM, Tom Honermann wrote:
> Attached is a patch to correct a lower bound search error that occurs
> when searching for module preprocessing entities within a source range.
>
> The test case I've been using for this is:
>
> $ cat t.c
> #if __GNUC__
> #endif
> void f(void) {
> }
>
> The problem I was having was that a query for macro expansions occurring
> within the definition of f() (source range 3:1-4:1) was returning the
> expansion of __GNUC__ occurring at line 1:5.  Clearly, no expansions
> should be found for that source range.
>
> The problem was due to lines 4315-4316 below.  The loop progressively
> reduces a half open range indicated by [First,First+Count) with PPI
> pointing to an element in the middle of that range.  Note that PPI is
> always dereferenceable - it is not a past-the-end iterator (indeed, it
> is unconditionally dereferenced at line 4313).
>
> If all of the source locations for the preprocessed entities precede the
> specified source location, then the loop will exit with PPI pointing to
> the last element in the range [pp_begin,pp_end).  However, the intention
> is that, if all entities precede the specified source location, then PPI
> is expected to point to pp_end (a past-the-end iterator) when the loop
> exits (see line 4322).  When the loop exits with PPI not set to pp_end,
> then it is interpreted as pointing to the first preprocessed entity with
> a source location following the specified location.  This is why my
> query is incorrectly including the preceding macro expansion.
>
> The attached patch against trunk (revision 189518) modifies lines
> 4315-4316 to first increment PPI, and then to assign First to PPI.  This
> causes PPI to be advanced appropriately to satisfy the comparison at
> line 4322 when all entities precede the specified source location.
>
> I looked for a simple way to provide a test for this behavior, but I
> wasn't able to find one.  It seems there may be some way to test this
> with c-index-test, but I wasn't able to figure out a way to do so (the
> problem only occurs when the relevant code is loaded from a PCH file).
> I'm afraid I'm not very familiar with the existing tests.  I did run the
> Clang test suite (make test) and no regressions were reported.
>
> lib/Serialization/ASTReader.cpp:
> 4280 /// \brief Returns the first preprocessed entity ID that ends after
> \arg BLoc.
> 4281 PreprocessedEntityID
> 4282 ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const {
> 4283   if (SourceMgr.isLocalSourceLocation(BLoc))
> 4284     return getTotalNumPreprocessedEntities();
> 4285
> 4286   GlobalSLocOffsetMapType::const_iterator
> 4287     SLocMapI =
> GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
> 4288                                         BLoc.getOffset() - 1);
> 4289   assert(SLocMapI != GlobalSLocOffsetMap.end() &&
> 4290          "Corrupted global sloc offset map");
> 4291
> 4292   if (SLocMapI->second->NumPreprocessedEntities == 0)
> 4293     return findNextPreprocessedEntity(SLocMapI);
> 4294
> 4295   ModuleFile &M = *SLocMapI->second;
> 4296   typedef const PPEntityOffset *pp_iterator;
> 4297   pp_iterator pp_begin = M.PreprocessedEntityOffsets;
> 4298   pp_iterator pp_end = pp_begin + M.NumPreprocessedEntities;
> 4299
> 4300   size_t Count = M.NumPreprocessedEntities;
> 4301   size_t Half;
> 4302   pp_iterator First = pp_begin;
> 4303   pp_iterator PPI;
> 4304
> 4305   // Do a binary search manually instead of using std::lower_bound
> because
> 4306   // The end locations of entities may be unordered (when a macro
> expansion
> 4307   // is inside another macro argument), but for this case it is not
> important
> 4308   // whether we get the first macro expansion or its containing macro.
> 4309   while (Count > 0) {
> 4310     Half = Count/2;
> 4311     PPI = First;
> 4312     std::advance(PPI, Half);
> 4313     if (SourceMgr.isBeforeInTranslationUnit(ReadSourceLocation(M,
> PPI->End),
> 4314                                             BLoc)){
> 4315       First = PPI;
> 4316       ++First;
> 4317       Count = Count - Half - 1;
> 4318     } else
> 4319       Count = Half;
> 4320   }
> 4321
> 4322   if (PPI == pp_end)
> 4323     return findNextPreprocessedEntity(SLocMapI);
> 4324
> 4325   return M.BasePreprocessedEntityID + (PPI - pp_begin);
> 4326 }
>
> Tom.
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: clang-module-find-pp-entity.patch
Type: text/x-patch
Size: 511 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130919/7525e100/attachment.bin>


More information about the cfe-dev mailing list