зеркало из https://github.com/microsoft/clang.git
Implement AST importing and merging for typedefs. As part of this, provide a lame implementation for importing TypeSourceInfos.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95783 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
0f962a8e61
Коммит
82fc4bfa6f
|
@ -17,6 +17,7 @@
|
|||
#include "clang/AST/ASTDiagnostic.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "clang/AST/TypeVisitor.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
|
@ -74,6 +75,7 @@ namespace {
|
|||
// Importing declarations
|
||||
Decl *VisitDecl(Decl *D);
|
||||
Decl *VisitVarDecl(VarDecl *D);
|
||||
Decl *VisitTypedefDecl(TypedefDecl *D);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -565,19 +567,9 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
TypeSourceInfo *TInfo = 0;
|
||||
if (TypeSourceInfo *FromTInfo = D->getTypeSourceInfo()) {
|
||||
TInfo = Importer.Import(FromTInfo);
|
||||
#if 0
|
||||
// FIXME: Tolerate failures in translation type source
|
||||
// information, at least until it is implemented.
|
||||
if (!TInfo)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Create the imported variable.
|
||||
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
|
||||
VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, Loc,
|
||||
Name.getAsIdentifierInfo(), T, TInfo,
|
||||
D->getStorageClass());
|
||||
|
@ -597,6 +589,74 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
|
|||
return ToVar;
|
||||
}
|
||||
|
||||
Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) {
|
||||
// Import the context of this declaration.
|
||||
DeclContext *DC = Importer.ImportContext(D->getDeclContext());
|
||||
if (!DC)
|
||||
return 0;
|
||||
|
||||
DeclContext *LexicalDC = DC;
|
||||
if (D->getDeclContext() != D->getLexicalDeclContext()) {
|
||||
LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
|
||||
if (!LexicalDC)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Import the name of this declaration.
|
||||
DeclarationName Name = Importer.Import(D->getDeclName());
|
||||
if (D->getDeclName() && !Name)
|
||||
return 0;
|
||||
|
||||
// Import the type of this declaration.
|
||||
QualType T = Importer.Import(D->getUnderlyingType());
|
||||
if (T.isNull())
|
||||
return 0;
|
||||
|
||||
// Import the location of this declaration.
|
||||
SourceLocation Loc = Importer.Import(D->getLocation());
|
||||
|
||||
// If this typedef is not in block scope, determine whether we've
|
||||
// seen a typedef with the same name (that we can merge with) or any
|
||||
// other entity by that name (which name lookup could conflict with).
|
||||
if (!DC->isFunctionOrMethod()) {
|
||||
llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
|
||||
unsigned IDNS = Decl::IDNS_Ordinary;
|
||||
for (DeclContext::lookup_result Lookup = DC->lookup(Name);
|
||||
Lookup.first != Lookup.second;
|
||||
++Lookup.first) {
|
||||
if (!(*Lookup.first)->isInIdentifierNamespace(IDNS))
|
||||
continue;
|
||||
if (TypedefDecl *FoundTypedef = dyn_cast<TypedefDecl>(*Lookup.first)) {
|
||||
if (Importer.getToContext().typesAreCompatible(T,
|
||||
FoundTypedef->getUnderlyingType())) {
|
||||
Importer.getImportedDecls()[D] = FoundTypedef;
|
||||
return FoundTypedef;
|
||||
}
|
||||
}
|
||||
|
||||
ConflictingDecls.push_back(*Lookup.first);
|
||||
}
|
||||
|
||||
if (!ConflictingDecls.empty()) {
|
||||
Name = Importer.HandleNameConflict(Name, DC, IDNS,
|
||||
ConflictingDecls.data(),
|
||||
ConflictingDecls.size());
|
||||
if (!Name)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the new typedef node.
|
||||
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
|
||||
TypedefDecl *ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC,
|
||||
Loc, Name.getAsIdentifierInfo(),
|
||||
TInfo);
|
||||
ToTypedef->setLexicalDeclContext(LexicalDC);
|
||||
Importer.getImportedDecls()[D] = ToTypedef;
|
||||
LexicalDC->addDecl(ToTypedef);
|
||||
return ToTypedef;
|
||||
}
|
||||
|
||||
ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
|
||||
Diagnostic &ToDiags,
|
||||
ASTContext &FromContext, FileManager &FromFileManager,
|
||||
|
@ -633,8 +693,18 @@ QualType ASTImporter::Import(QualType FromT) {
|
|||
}
|
||||
|
||||
TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
|
||||
// FIXME: Implement!
|
||||
return 0;
|
||||
if (!FromTSI)
|
||||
return FromTSI;
|
||||
|
||||
// FIXME: For now we just create a "trivial" type source info based
|
||||
// on the type and a seingle location. Implement a real version of
|
||||
// this.
|
||||
QualType T = Import(FromTSI->getType());
|
||||
if (T.isNull())
|
||||
return 0;
|
||||
|
||||
return ToContext.getTrivialTypeSourceInfo(T,
|
||||
FromTSI->getTypeLoc().getFullSourceRange().getBegin());
|
||||
}
|
||||
|
||||
Decl *ASTImporter::Import(Decl *FromD) {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
typedef int Typedef1;
|
||||
typedef int Typedef2;
|
||||
Typedef1 x1;
|
||||
Typedef2 x2;
|
|
@ -0,0 +1,4 @@
|
|||
typedef int Typedef1;
|
||||
typedef double Typedef2;
|
||||
Typedef1 x1;
|
||||
Typedef2 x2;
|
|
@ -0,0 +1,7 @@
|
|||
// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/typedef1.c
|
||||
// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/typedef2.c
|
||||
// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
|
||||
|
||||
// CHECK: typedef2.c:4:10: error: external variable 'x2' declared with incompatible types in different translation units ('Typedef2' (aka 'double') vs. 'Typedef2' (aka 'int'))
|
||||
// CHECK: typedef1.c:4:10: note: declared here with type 'Typedef2' (aka 'int')
|
||||
// CHECK: 2 diagnostics
|
|
@ -9,3 +9,4 @@
|
|||
// CHECK: var1.h:1:8: note: declared here with type 'double'
|
||||
// CHECK: error: external variable 'xarray3' declared with incompatible types in different translation units ('int [17]' vs. 'int [18]')
|
||||
// CHECK: var1.c:7:5: note: declared here with type 'int [18]'
|
||||
// CHECK: 6 diagnostics
|
||||
|
|
Загрузка…
Ссылка в новой задаче