Summary:
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:
PDOMWriter.java:
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.
Details:
This test code has been reduced from larger files.
src.c:
#include "h1.h"
#include "h2.h"
int m1 = MACRO;
h1.h:
#ifndef H1
#define H1
#include "h1a.h" // line 5 (see below)
#undef D1
#include "h1a.h" // line 7 (see below)
#endif
h1a.h:
extern int i;
#ifndef H1a
#define H1a
#define D1
#endif
h2.h:
#define MACRO 1
#ifdef D1
#endif
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.
-Andrew