From: Douglas Gregor Date: Wed, 10 Feb 2010 17:47:19 +0000 (+0000) Subject: Implement AST importing and merging for typedefs. As part of this, provide a lame... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=82fc4bfa6f8ea35488b9038dd83d40766c3645cf;p=clang 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 --- diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 9fb695e4e1..5201f29b90 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -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 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(*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) { diff --git a/test/ASTMerge/Inputs/typedef1.c b/test/ASTMerge/Inputs/typedef1.c new file mode 100644 index 0000000000..5657675685 --- /dev/null +++ b/test/ASTMerge/Inputs/typedef1.c @@ -0,0 +1,4 @@ +typedef int Typedef1; +typedef int Typedef2; +Typedef1 x1; +Typedef2 x2; diff --git a/test/ASTMerge/Inputs/typedef2.c b/test/ASTMerge/Inputs/typedef2.c new file mode 100644 index 0000000000..129d7101e9 --- /dev/null +++ b/test/ASTMerge/Inputs/typedef2.c @@ -0,0 +1,4 @@ +typedef int Typedef1; +typedef double Typedef2; +Typedef1 x1; +Typedef2 x2; diff --git a/test/ASTMerge/typedef.c b/test/ASTMerge/typedef.c new file mode 100644 index 0000000000..4498864b49 --- /dev/null +++ b/test/ASTMerge/typedef.c @@ -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 diff --git a/test/ASTMerge/var.c b/test/ASTMerge/var.c index 06bebd5ee8..fd307940af 100644 --- a/test/ASTMerge/var.c +++ b/test/ASTMerge/var.c @@ -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