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:
Douglas Gregor 2010-02-10 17:47:19 +00:00
Родитель 0f962a8e61
Коммит 82fc4bfa6f
5 изменённых файлов: 100 добавлений и 14 удалений

Просмотреть файл

@ -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;

7
test/ASTMerge/typedef.c Normal file
Просмотреть файл

@ -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