Fix assert failure with duplicate decls.

When generating the GQt module in rootcling, we hit the assertions
in forceAppend assertions about "Duplicates?!" with this declaration:

```
CXXRecordDecl 0x55555643fae8 </usr/include/qt4/QtCore/qglobal.h:1658:1, line:1794:1> line:1658:21 in GQt.TGQt.h hidden class QSysInfo definition
|-also in GQt.TQtClientWidget.h
|-CXXRecordDecl 0x55555643fc30 <col:1, col:21> col:21 in GQt.TGQt.h hidden implicit class QSysInfo
|-AccessSpecDecl 0x55555643fce8 <line:1659:1, col:7> col:1 in GQt.TGQt.h public
|-EnumDecl 0x55555643fd18 <line:1660:5, line:1662:5> line:1660:10 in GQt.TGQt.h hidden Sizes
| `-EnumConstantDecl 0x55555643fe98 <line:1661:9, col:38> col:9 in GQt.TGQt.h hidden WordSize 'enum QSysInfo::Sizes'
|   `-ImplicitCastExpr 0x55555643fee0 <col:20, col:38> 'unsigned int' <IntegralCast>
|     `-ParenExpr 0x55555643fe70 <col:20, col:38> 'unsigned long'
|       `-BinaryOperator 0x55555643fe48 <col:21, col:37> 'unsigned long' '<<'
|         |-UnaryExprOrTypeTraitExpr 0x55555643fe08 <col:21, col:34> 'unsigned long' sizeof 'void *'
|         `-IntegerLiteral 0x55555643fe28 <col:37> 'int' 3
`-EnumDecl 0x55555643ff00 <line:1672:5, line:1685:5> line:1672:10 in GQt.TGQt.h hidden Endian
  |-EnumConstantDecl 0x55555643ffd8 <line:1673:9> col:9 in GQt.TGQt.h hidden referenced BigEndian 'enum QSysInfo::Endian'
  |-EnumConstantDecl 0x555556440028 <line:1674:9> col:9 in GQt.TGQt.h hidden referenced LittleEndian 'enum QSysInfo::Endian'
  `-EnumConstantDecl 0x5555564400a0 <line:1681:11, col:23> col:11 in GQt.TGQt.h hidden ByteOrder 'enum QSysInfo::Endian'
    `-ImplicitCastExpr 0x5555564400e8 <col:23> 'unsigned int' <IntegralCast>
      `-DeclRefExpr 0x555556440070 <col:23> 'int' EnumConstant 0x555556440028 'LittleEndian' 'enum QSysInfo::Endian'
```

The reason for this is that we have QSysInfo both in the TQtClientWidget
and TGQt submodules and our current translation (which is supposed to
parse all header in the module) sees them both in one transaction.

As we also don't recognize that this decl is from a module, the code
fires the assert even though duplictes are expected with modules.

The reason why we don't recognize it as a declaration form an ASTFile
which disables the assert is that FromASTFile for the decls is
not set. This is because they haven't been loaded by the ASTFileReader
but are directly parsed as submodules in our special case where we
directly parse a module content from rootcling to generate it.

We just workaround in this patch by checking that if the decl is from
the currently generated module, we are pretending it's as if it was
loaded from an AST file.
This commit is contained in:
Raphael Isemann 2017-10-26 16:42:15 +02:00 committed by sftnight
parent f081e145e8
commit 99d1df55ae

View File

@ -382,7 +382,26 @@ namespace cling {
// Take the first/only decl in the group.
Decl* D = *DGR.begin();
return D->isFromASTFile();
// If D is from an AST file, we can return true.
if (D->isFromASTFile()) return true;
if (m_Sema.getASTContext().getLangOpts().Modules) {
// If we currently compile a module and the decl is from a submodule that
// we are currently compiling, then we also pretend it's from a AST file.
// If we don't do that than our duplicate check in forceAppend will fail
// when we try to generate a module that has multiple submodules that
// textually include the same declaration (which will cause multiple
// entries of the same merged decl to be in this list).
if (D->getOwningModule()) {
StringRef CurrentModule =
D->getASTContext().getLangOpts().CurrentModule;
StringRef DeclModule = D->getOwningModule()->getTopLevelModuleName();
return CurrentModule == DeclModule;
}
}
return false;
}
SourceLocation