[cfe-dev] Out of date IdentifierInfo instances associated with macro expansions loaded from AST files

Tom Honermann thonermann at coverity.com
Fri Aug 30 12:32:55 PDT 2013


Attached is a patch against Clang trunk to correct IdentifierInfo 
associations for macro definitions and expansions read from AST files 
when the name of the macro matches the name of another identifier (such 
as a keyword).

I'm not particularly confident that the patch represents the best way to 
correct this issue, so further review and comments would be appreciated. 
  No regressions occurred when running the Clang test suite with this 
change in place.

For testing, I've been using this code that defines a macro with the 
same name as a keyword.

$ cat t.c
#define register
void f(void) {
   register int i;
}

The code is then compiled and emitted to a .ast file with a detailed 
preprocessing record.  An in-house utility is then used to read it.

$ clang -emit-ast -Xclang -detailed-preprocessing-record t.c

The problem occurs when attempting to retrieve macro information 
associated with macro expansions within a source range.  I don't have a 
standalone test case I can share, but the relevant code looks similar to 
this:

void f(Preprocessor &preprocessor, const SourceRange &range) {
   PreprocessingRecord *preprocessing_record
     = preprocessor.getPreprocessingRecord();

   std::pair<
     PreprocessingRecord::iterator,
     PreprocessingRecord::iterator> preproc_range
     = preprocessing_record->getPreprocessedEntitiesInRange(range));

   PreprocessingRecord::iterator preproc_current = preproc_range.first;
   PreprocessingRecord::iterator preproc_end = preproc_range.second;
   for (; preproc_current != preproc_end; ++preproc_current) {
     MacroExpansion* macro_expansion
       = dyn_cast<MacroExpansion>(*preproc_current));
     if (!macro_expansion)
       continue;

     const IdentifierInfo *macro_id = macro_expansion->getName();
     const MacroInfo *macro_info = preprocessor.getMacroInfo(
       const_cast<IdentifierInfo*>(macro_id));
     if (!macro_info && macro_id->hadMacroDefinition()) {
       // The identifier does not correspond to a currently
       // (at end of TU) defined macro.  Get the most recently
       // #undef'd definition.
       macro_info = preprocessor.getMacroInfoHistory(
         const_cast<IdentifierInfo*>(macro_id));
     }
     assert(macro_info &&
       "Encountered a macro expansion with no definition history");
   }
}

The assert at the end fails for the test case above.  The reason is that 
the IdentifierInfo instance retrieved from the MacroExpansion instance 
is an out of date instance (macro_id->OutOfDate == true) corresponding 
to the "register" keyword and neither hasMacroDefinition() nor 
hadMacroDefinition() return true for it (Preprocessor::getMacroInfo() 
return NULL because macro_id->hasMacroDefinition() returns false).

The patch corrects this by changing ASTReader::DecodeIdentifierInfo() to 
check if calls to IdentifierTable::get() return an out of date 
IdentifierInfo instance and, if so, to explicitly retrieve an 
IdentifierInfo instance from the external identifier lookup instance 
associated with the PP.getIdentifierTable() IdentifierTable instance. 
This causes MacroExpansion (and MacroDefinition) instances to be 
deserialized with the correctly preserved IdentifierInfo associations.

I had also tried updating IdentifierTable::get() to check if it is about 
to return an out of date IdentifierInfo instance and, if so, to check 
for an external instance and preferentially return that.  This change 
also resolved the problem for me, but triggered a single regression in 
the Clang test suite (test/PCH/pch__VA_ARGS__.c).  I did not research 
further why that test case failed and moved on to a more localized solution.

Tom.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: clang-module-identifier-out-of-date.patch
Type: text/x-patch
Size: 1027 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130830/aaa3152e/attachment.bin>


More information about the cfe-dev mailing list