Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-dev] PDOMWriter and IncludeInformation

I have a source file with two #include statements. The PDOMFile that is created has a list of three PDOMIncludes. This doesn't seem valid, I think the conditional on line 601 of PDOMWriter is backward:
600: for (ISignificantMacros sig : stmt.getLoadedVersions()) {
601:     if (!sig.equals(mainSig)) {
602:         includeInfos.add(new IncludeInformation(stmt, targetLoc, sig, false));
603:     }
604: }
605: final boolean isContext = stmt.isActive() && stmt.isResolved() &&
606:         (data.fContextIncludes.contains(stmt) || isContextFor(oldFile, stmt));
607: includeInfos.add(new IncludeInformation(stmt, targetLoc, mainSig, isContext));

It would make sense to me if that condition were saying “If there is already an IncludeInfo and its significant macros are the same as what is needed, then reuse that IncludeInfo.”

The part of the hypothesis that confuses me is line 607. It seems that if things really are as simple as that, then there should be something to ensure that only one of 601 and 607 are executed. Also, the loop on line 600 should be aborted when an existing IncludeInfo is chosen.

Are there cases where there should be more than one IncludeInformation for a single #include directive?

I‘ll create a bug to track this. I’m sending the email now in case someone can correct my logic. I don‘t really understand the pragma-once handling which is what the code’s checkin comment references.

The rest of this (long) email describes how I got to this point.

This test code has been reduced from larger files.

#include "h1.h"
#include "h2.h"
int m1 = MACRO; // ProblemBinding for MACRO

#ifndef H1
#define H1

#include "h1a.h" // line 5 (see below)
#undef D1
#include "h1a.h" // line 7 (see below)


extern int i;
#ifndef H1a
#define H1a
#define D1

#define MACRO 1
#ifdef D1

With the current implementation the reference to MACRO is not resolved in src.c and there is a ProblemBinding in the initialization clause.

Here is a trace of the PDOMIncludes that are stored into the PDOMFile for h1.h:

PDOMFile(5498) /JI449520-C2/src/h1.h {}
PDOMInclude(5802) stmt-line 5 ‘#include “h1a.h”’ -> PDOMFile(4506)
PDOMInclude(5834) stmt-line 7 ‘#include “h1a.h”’ -> PDOMFile(4506)
PDOMInclude(5866) stmt-line 7 ‘#include “h1a.h”’ -> PDOMFile(5330)

I think that the first and third PDOMInclude instances are valid, but the second one is not.

The trouble with the second instance is that it is created from the #include on line 7, but it points to the PDOMFile that has the same context as the #include on line 5.

The reason this causes the problem binding is as follows.

h2.h is stored into the index with D1 being a significant macro. The CPreprocessor.fCurrentContext says that D1 is undefined at this point (from line 6 of h1.h). The index lookup code ensures that h2.h will only be used in contexts where D1 is not defined.

h1a.h is stored into the index two times. The first time the fCurrentContext says that H1a is not defined, the second time it says that H1a is defined. The first version of the file has the directive #define D1, the second version does not.

When CReconciler processes the #include‘s in src.c is has problems while processing h1.h. It processes the first instance of h1a.h including the #define’s D1; D1 is added to the fMacroDictionary. Good.

Then it processes the #undef D1 and removes the value. Good.

Then it processes the first instance of h1a.h again. This puts D1 back into the fMacroDictionary. Oh-oh.

Later the processor tries to handle h2.h. The version of this file that is in the index requires D1 to be undefined — which it is not. We don't get to use the indexed version of h2.h and have to look at the source code. However, PREF_USE_STRUCTURAL_PARSE_MODE is set to false, so it ignores the content of the file. The #define MACRO directive is not found.


Back to the top