[cfe-commits] r95900 - in /cfe/trunk: include/clang/AST/ASTImporter.h include/clang/Basic/DiagnosticASTKinds.td lib/AST/ASTImporter.cpp lib/Frontend/ASTMerge.cpp test/ASTMerge/Inputs/struct1.c test/ASTMerge/Inputs/struct2.c test/ASTMerge/struct.c
Douglas Gregor
dgregor at apple.com
Thu Feb 11 11:21:55 PST 2010
Author: dgregor
Date: Thu Feb 11 13:21:55 2010
New Revision: 95900
URL: http://llvm.org/viewvc/llvm-project?rev=95900&view=rev
Log:
When AST merging for record declarations fails, warn about the
incompatibility and show where the structural differences are. For
example:
struct1.c:36:8: warning: type 'struct S7' has incompatible definitions
in different translation units
struct S7 { int i : 8; unsigned j : 8; } x7;
^
struct1.c:36:33: note: bit-field 'j' with type 'unsigned int' and length 8 here
struct S7 { int i : 8; unsigned j : 8; } x7;
^
struct2.c:33:33: note: bit-field 'j' with type 'unsigned int' and length 16 here
struct S7 { int i : 8; unsigned j : 16; } x7;
^
There are a few changes to make this work:
- ASTImporter now has only a single Diagnostic object, not multiple
diagnostic objects. Otherwise, having a warning/error printed via
one Diagnostic and its note printed on the other Diagnostic could
cause the note to be suppressed.
- Implemented import functionality for IntegerLiteral (along with
general support for statements and expressions)
Modified:
cfe/trunk/include/clang/AST/ASTImporter.h
cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
cfe/trunk/lib/AST/ASTImporter.cpp
cfe/trunk/lib/Frontend/ASTMerge.cpp
cfe/trunk/test/ASTMerge/Inputs/struct1.c
cfe/trunk/test/ASTMerge/Inputs/struct2.c
cfe/trunk/test/ASTMerge/struct.c
Modified: cfe/trunk/include/clang/AST/ASTImporter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=95900&r1=95899&r2=95900&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTImporter.h (original)
+++ cfe/trunk/include/clang/AST/ASTImporter.h Thu Feb 11 13:21:55 2010
@@ -40,9 +40,8 @@
/// \brief The file managers we're importing to and from.
FileManager &ToFileManager, &FromFileManager;
- /// \brief The diagnostics object that we should use to emit diagnostics
- /// within the context we're importing to and from.
- Diagnostic &ToDiags, &FromDiags;
+ /// \brief The diagnostics object that we should use to emit diagnostics.
+ Diagnostic &Diags;
/// \brief Mapping from the already-imported types in the "from" context
/// to the corresponding types in the "to" context.
@@ -51,16 +50,19 @@
/// \brief Mapping from the already-imported declarations in the "from"
/// context to the corresponding declarations in the "to" context.
llvm::DenseMap<Decl *, Decl *> ImportedDecls;
-
+
+ /// \brief Mapping from the already-imported statements in the "from"
+ /// context to the corresponding statements in the "to" context.
+ llvm::DenseMap<Stmt *, Stmt *> ImportedStmts;
+
/// \brief Mapping from the already-imported FileIDs in the "from" source
/// manager to the corresponding FileIDs in the "to" source manager.
llvm::DenseMap<unsigned, FileID> ImportedFileIDs;
public:
- ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
- Diagnostic &ToDiags,
- ASTContext &FromContext, FileManager &FromFileManager,
- Diagnostic &FromDiags);
+ ASTImporter(Diagnostic &Diags,
+ ASTContext &ToContext, FileManager &ToFileManager,
+ ASTContext &FromContext, FileManager &FromFileManager);
virtual ~ASTImporter();
@@ -191,14 +193,6 @@
/// \brief Retrieve the file manager that AST nodes are being imported from.
FileManager &getFromFileManager() const { return FromFileManager; }
- /// \brief Retrieve the diagnostics object to use to report errors within
- /// the context we're importing into.
- Diagnostic &getToDiags() const { return ToDiags; }
-
- /// \brief Retrieve the diagnostics object to use to report errors within
- /// the context we're importing from.
- Diagnostic &getFromDiags() const { return FromDiags; }
-
/// \brief Retrieve the mapping from declarations in the "from" context
/// to the already-imported declarations in the "to" context.
llvm::DenseMap<Decl *, Decl *> &getImportedDecls() { return ImportedDecls; }
Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=95900&r1=95899&r2=95900&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Thu Feb 11 13:21:55 2010
@@ -37,5 +37,19 @@
def err_odr_function_type_inconsistent : Error<
"external function %0 declared with incompatible types in different "
"translation units (%1 vs. %2)">;
+def warn_odr_class_type_inconsistent : Warning<
+ "type %0 has incompatible definitions in different translation units">;
+def note_odr_tag_kind_here: Note<
+ "%0 is a %select{struct|union|class|enum}1 here">;
+def note_odr_field : Note<"field %0 has type %1 here">;
+def note_odr_missing_field : Note<"no corresponding field here">;
+def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">;
+def note_odr_not_bit_field : Note<"field %0 is not a bit-field">;
+def note_odr_base : Note<"class has base type %0">;
+def note_odr_virtual_base : Note<
+ "%select{non-virtual|virtual}0 derivation here">;
+def note_odr_missing_base : Note<"no corresponding base class here">;
+def note_odr_number_of_bases : Note<
+ "class has %0 base %plural{1:class|:classes}0">;
def err_unsupported_ast_node: Error<"cannot import unsupported AST node %0">;
}
Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=95900&r1=95899&r2=95900&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Feb 11 13:21:55 2010
@@ -18,6 +18,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/FileManager.h"
@@ -28,7 +29,8 @@
namespace {
class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>,
- public DeclVisitor<ASTNodeImporter, Decl *> {
+ public DeclVisitor<ASTNodeImporter, Decl *>,
+ public StmtVisitor<ASTNodeImporter, Stmt *> {
ASTImporter &Importer;
public:
@@ -36,6 +38,7 @@
using TypeVisitor<ASTNodeImporter, QualType>::Visit;
using DeclVisitor<ASTNodeImporter, Decl *>::Visit;
+ using StmtVisitor<ASTNodeImporter, Stmt *>::Visit;
// Importing types
QualType VisitType(Type *T);
@@ -89,6 +92,13 @@
Decl *VisitFieldDecl(FieldDecl *D);
Decl *VisitVarDecl(VarDecl *D);
Decl *VisitParmVarDecl(ParmVarDecl *D);
+
+ // Importing statements
+ Stmt *VisitStmt(Stmt *S);
+
+ // Importing expressions
+ Expr *VisitExpr(Expr *E);
+ Expr *VisitIntegerLiteral(IntegerLiteral *E);
};
}
@@ -506,37 +516,81 @@
bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
RecordDecl *ToRecord) {
- // FIXME: If we know that the two records are the same according to the ODR,
- // we could diagnose structural mismatches here. However, we don't really
- // have that information.
- if (FromRecord->isUnion() != ToRecord->isUnion())
+ if (FromRecord->isUnion() != ToRecord->isUnion()) {
+ Importer.ToDiag(ToRecord->getLocation(),
+ diag::warn_odr_class_type_inconsistent)
+ << Importer.getToContext().getTypeDeclType(ToRecord);
+ Importer.FromDiag(FromRecord->getLocation(), diag::note_odr_tag_kind_here)
+ << FromRecord->getDeclName() << (unsigned)FromRecord->getTagKind();
return false;
-
+ }
+
if (CXXRecordDecl *FromCXX = dyn_cast<CXXRecordDecl>(FromRecord)) {
if (CXXRecordDecl *ToCXX = dyn_cast<CXXRecordDecl>(ToRecord)) {
- if (FromCXX->getNumBases() != ToCXX->getNumBases())
+ if (FromCXX->getNumBases() != ToCXX->getNumBases()) {
+ Importer.ToDiag(ToRecord->getLocation(),
+ diag::warn_odr_class_type_inconsistent)
+ << Importer.getToContext().getTypeDeclType(ToRecord);
+ Importer.ToDiag(ToRecord->getLocation(), diag::note_odr_number_of_bases)
+ << ToCXX->getNumBases();
+ Importer.FromDiag(FromRecord->getLocation(),
+ diag::note_odr_number_of_bases)
+ << FromCXX->getNumBases();
return false;
-
+ }
+
// Check the base classes.
for (CXXRecordDecl::base_class_iterator FromBase = FromCXX->bases_begin(),
FromBaseEnd = FromCXX->bases_end(),
ToBase = ToCXX->bases_begin();
FromBase != FromBaseEnd;
- ++FromBase, ++ToBase) {
- // Check virtual vs. non-virtual inheritance mismatch.
- if (FromBase->isVirtual() != ToBase->isVirtual())
- return false;
-
+ ++FromBase, ++ToBase) {
// Check the type we're inheriting from.
QualType FromBaseT = Importer.Import(FromBase->getType());
if (FromBaseT.isNull())
return false;
if (!Importer.getToContext().typesAreCompatible(FromBaseT,
- ToBase->getType()))
+ ToBase->getType())) {
+ Importer.ToDiag(ToRecord->getLocation(),
+ diag::warn_odr_class_type_inconsistent)
+ << Importer.getToContext().getTypeDeclType(ToRecord);
+ Importer.ToDiag(ToBase->getSourceRange().getBegin(),
+ diag::note_odr_base)
+ << ToBase->getType()
+ << ToBase->getSourceRange();
+ Importer.FromDiag(FromBase->getSourceRange().getBegin(),
+ diag::note_odr_base)
+ << FromBase->getType()
+ << FromBase->getSourceRange();
return false;
+ }
+
+ // Check virtual vs. non-virtual inheritance mismatch.
+ if (FromBase->isVirtual() != ToBase->isVirtual()) {
+ Importer.ToDiag(ToRecord->getLocation(),
+ diag::warn_odr_class_type_inconsistent)
+ << Importer.getToContext().getTypeDeclType(ToRecord);
+ Importer.ToDiag(ToBase->getSourceRange().getBegin(),
+ diag::note_odr_virtual_base)
+ << ToBase->isVirtual() << ToBase->getSourceRange();
+ Importer.FromDiag(FromBase->getSourceRange().getBegin(),
+ diag::note_odr_base)
+ << FromBase->isVirtual()
+ << FromBase->getSourceRange();
+ return false;
+ }
}
} else if (FromCXX->getNumBases() > 0) {
+ Importer.ToDiag(ToRecord->getLocation(),
+ diag::warn_odr_class_type_inconsistent)
+ << Importer.getToContext().getTypeDeclType(ToRecord);
+ const CXXBaseSpecifier *FromBase = FromCXX->bases_begin();
+ Importer.FromDiag(FromBase->getSourceRange().getBegin(),
+ diag::note_odr_base)
+ << FromBase->getType()
+ << FromBase->getSourceRange();
+ Importer.ToDiag(ToRecord->getLocation(), diag::note_odr_missing_base);
return false;
}
}
@@ -548,19 +602,58 @@
FromFieldEnd = FromRecord->field_end();
FromField != FromFieldEnd;
++FromField, ++ToField) {
- if (ToField == ToFieldEnd)
+ if (ToField == ToFieldEnd) {
+ Importer.ToDiag(ToRecord->getLocation(),
+ diag::warn_odr_class_type_inconsistent)
+ << Importer.getToContext().getTypeDeclType(ToRecord);
+ Importer.FromDiag(FromField->getLocation(), diag::note_odr_field)
+ << FromField->getDeclName() << FromField->getType();
+ Importer.ToDiag(ToRecord->getLocation(), diag::note_odr_missing_field);
return false;
-
+ }
+
QualType FromT = Importer.Import(FromField->getType());
if (FromT.isNull())
return false;
- if (FromField->isBitField() != ToField->isBitField())
+ if (!Importer.getToContext().typesAreCompatible(FromT, ToField->getType())){
+ Importer.ToDiag(ToRecord->getLocation(),
+ diag::warn_odr_class_type_inconsistent)
+ << Importer.getToContext().getTypeDeclType(ToRecord);
+ Importer.ToDiag(ToField->getLocation(), diag::note_odr_field)
+ << ToField->getDeclName() << ToField->getType();
+ Importer.FromDiag(FromField->getLocation(), diag::note_odr_field)
+ << FromField->getDeclName() << FromField->getType();
return false;
+ }
- if (!Importer.getToContext().typesAreCompatible(FromT, ToField->getType()))
+ if (FromField->isBitField() != ToField->isBitField()) {
+ Importer.ToDiag(ToRecord->getLocation(),
+ diag::warn_odr_class_type_inconsistent)
+ << Importer.getToContext().getTypeDeclType(ToRecord);
+ if (FromField->isBitField()) {
+ llvm::APSInt Bits;
+ FromField->getBitWidth()->isIntegerConstantExpr(Bits,
+ Importer.getFromContext());
+ Importer.FromDiag(FromField->getLocation(), diag::note_odr_bit_field)
+ << FromField->getDeclName() << FromField->getType()
+ << Bits.toString(10, false);
+ Importer.ToDiag(ToField->getLocation(), diag::note_odr_not_bit_field)
+ << ToField->getDeclName();
+ } else {
+ llvm::APSInt Bits;
+ ToField->getBitWidth()->isIntegerConstantExpr(Bits,
+ Importer.getToContext());
+ Importer.ToDiag(ToField->getLocation(), diag::note_odr_bit_field)
+ << ToField->getDeclName() << ToField->getType()
+ << Bits.toString(10, false);
+ Importer.FromDiag(FromField->getLocation(),
+ diag::note_odr_not_bit_field)
+ << FromField->getDeclName();
+ }
return false;
-
+ }
+
if (FromField->isBitField()) {
// Make sure that the bit-fields are the same length.
llvm::APSInt FromBits, ToBits;
@@ -579,12 +672,32 @@
FromBits.setIsUnsigned(true);
ToBits.setIsUnsigned(true);
- if (FromBits != ToBits)
+ if (FromBits != ToBits) {
+ Importer.ToDiag(ToRecord->getLocation(),
+ diag::warn_odr_class_type_inconsistent)
+ << Importer.getToContext().getTypeDeclType(ToRecord);
+ Importer.ToDiag(ToField->getLocation(), diag::note_odr_bit_field)
+ << ToField->getDeclName() << ToField->getType()
+ << ToBits.toString(10, false);
+ Importer.FromDiag(FromField->getLocation(), diag::note_odr_bit_field)
+ << FromField->getDeclName() << FromField->getType()
+ << FromBits.toString(10, false);
return false;
+ }
}
}
- return ToField == ToFieldEnd;
+ if (ToField != ToFieldEnd) {
+ Importer.ToDiag(ToRecord->getLocation(),
+ diag::warn_odr_class_type_inconsistent)
+ << Importer.getToContext().getTypeDeclType(ToRecord);
+ Importer.ToDiag(ToField->getLocation(), diag::note_odr_field)
+ << ToField->getDeclName() << ToField->getType();
+ Importer.FromDiag(FromRecord->getLocation(), diag::note_odr_missing_field);
+ return false;
+ }
+
+ return true;
}
Decl *ASTNodeImporter::VisitDecl(Decl *D) {
@@ -691,11 +804,14 @@
}
if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) {
- if (IsStructuralMatch(D, FoundRecord)) {
+ RecordDecl *FoundDef = FoundRecord->getDefinition();
+ // FIXME: If we found something but there is no definition,
+ // assume the types are the same and fill in the gaps.
+ if (FoundDef && IsStructuralMatch(D, FoundDef)) {
// The record types structurally match.
// FIXME: For C++, we should also merge methods here.
- Importer.getImportedDecls()[D] = FoundRecord;
- return FoundRecord;
+ Importer.getImportedDecls()[D] = FoundDef;
+ return FoundDef;
}
}
@@ -1026,13 +1142,40 @@
return ToParm;
}
-ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
- Diagnostic &ToDiags,
- ASTContext &FromContext, FileManager &FromFileManager,
- Diagnostic &FromDiags)
+//----------------------------------------------------------------------------
+// Import Statements
+//----------------------------------------------------------------------------
+
+Stmt *ASTNodeImporter::VisitStmt(Stmt *S) {
+ Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node)
+ << S->getStmtClassName();
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// Import Expressions
+//----------------------------------------------------------------------------
+Expr *ASTNodeImporter::VisitExpr(Expr *E) {
+ Importer.FromDiag(E->getLocStart(), diag::err_unsupported_ast_node)
+ << E->getStmtClassName();
+ return 0;
+}
+
+Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return 0;
+
+ return new (Importer.getToContext())
+ IntegerLiteral(E->getValue(), T, Importer.Import(E->getLocation()));
+}
+
+ASTImporter::ASTImporter(Diagnostic &Diags,
+ ASTContext &ToContext, FileManager &ToFileManager,
+ ASTContext &FromContext, FileManager &FromFileManager)
: ToContext(ToContext), FromContext(FromContext),
ToFileManager(ToFileManager), FromFileManager(FromFileManager),
- ToDiags(ToDiags), FromDiags(FromDiags) {
+ Diags(Diags) {
ImportedDecls[FromContext.getTranslationUnitDecl()]
= ToContext.getTranslationUnitDecl();
}
@@ -1114,8 +1257,20 @@
if (!FromS)
return 0;
- // FIXME: Implement!
- return 0;
+ // Check whether we've already imported this declaration.
+ llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS);
+ if (Pos != ImportedStmts.end())
+ return Pos->second;
+
+ // Import the type
+ ASTNodeImporter Importer(*this);
+ Stmt *ToS = Importer.Visit(FromS);
+ if (!ToS)
+ return 0;
+
+ // Record the imported declaration.
+ ImportedStmts[FromS] = ToS;
+ return ToS;
}
NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
@@ -1259,11 +1414,11 @@
}
DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) {
- return ToDiags.Report(FullSourceLoc(Loc, ToContext.getSourceManager()),
- DiagID);
+ return Diags.Report(FullSourceLoc(Loc, ToContext.getSourceManager()),
+ DiagID);
}
DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) {
- return FromDiags.Report(FullSourceLoc(Loc, FromContext.getSourceManager()),
- DiagID);
+ return Diags.Report(FullSourceLoc(Loc, FromContext.getSourceManager()),
+ DiagID);
}
Modified: cfe/trunk/lib/Frontend/ASTMerge.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTMerge.cpp?rev=95900&r1=95899&r2=95900&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTMerge.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTMerge.cpp Thu Feb 11 13:21:55 2010
@@ -37,21 +37,16 @@
CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
&CI.getASTContext());
for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
- Diagnostic ASTDiags(CI.getDiagnostics().getClient());
-
- ASTUnit *Unit = ASTUnit::LoadFromPCHFile(ASTFiles[I], ASTDiags,
+ ASTUnit *Unit = ASTUnit::LoadFromPCHFile(ASTFiles[I], CI.getDiagnostics(),
false, true);
if (!Unit)
continue;
- ASTDiags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
- &Unit->getASTContext());
- ASTImporter Importer(CI.getASTContext(),
+ ASTImporter Importer(CI.getDiagnostics(),
+ CI.getASTContext(),
CI.getFileManager(),
- CI.getDiagnostics(),
Unit->getASTContext(),
- Unit->getFileManager(),
- ASTDiags);
+ Unit->getFileManager());
TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
for (DeclContext::decl_iterator D = TU->decls_begin(),
Modified: cfe/trunk/test/ASTMerge/Inputs/struct1.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/Inputs/struct1.c?rev=95900&r1=95899&r2=95900&view=diff
==============================================================================
--- cfe/trunk/test/ASTMerge/Inputs/struct1.c (original)
+++ cfe/trunk/test/ASTMerge/Inputs/struct1.c Thu Feb 11 13:21:55 2010
@@ -1,6 +1,7 @@
typedef int Int;
typedef float Float;
+// Matches
struct S0 {
Int field1;
Float field2;
@@ -8,9 +9,28 @@
struct S0 x0;
+// Mismatch in field type
struct S1 {
Int field1;
int field2;
};
struct S1 x1;
+
+// Mismatch in tag kind.
+struct S2 { int i; float f; } x2;
+
+// Missing fields
+struct S3 { int i; float f; double d; } x3;
+
+// Extra fields
+struct S4 { int i; } x4;
+
+// Bit-field matches
+struct S5 { int i : 8; unsigned j : 8; } x5;
+
+// Bit-field mismatch
+struct S6 { int i : 8; unsigned j : 8; } x6;
+
+// Bit-field mismatch
+struct S7 { int i : 8; unsigned j : 8; } x7;
Modified: cfe/trunk/test/ASTMerge/Inputs/struct2.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/Inputs/struct2.c?rev=95900&r1=95899&r2=95900&view=diff
==============================================================================
--- cfe/trunk/test/ASTMerge/Inputs/struct2.c (original)
+++ cfe/trunk/test/ASTMerge/Inputs/struct2.c Thu Feb 11 13:21:55 2010
@@ -1,3 +1,4 @@
+// Matches
struct S0 {
int field1;
float field2;
@@ -5,9 +6,28 @@
struct S0 x0;
+// Mismatch in field type
struct S1 {
int field1;
float field2;
};
struct S1 x1;
+
+// Mismatch in tag kind.
+union S2 { int i; float f; } x2;
+
+// Missing fields
+struct S3 { int i; float f; } x3;
+
+// Extra fields
+struct S4 { int i; float f; } x4;
+
+// Bit-field matches
+struct S5 { int i : 8; unsigned j : 8; } x5;
+
+// Bit-field mismatch
+struct S6 { int i : 8; unsigned j; } x6;
+
+// Bit-field mismatch
+struct S7 { int i : 8; unsigned j : 16; } x7;
Modified: cfe/trunk/test/ASTMerge/struct.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/struct.c?rev=95900&r1=95899&r2=95900&view=diff
==============================================================================
--- cfe/trunk/test/ASTMerge/struct.c (original)
+++ cfe/trunk/test/ASTMerge/struct.c Thu Feb 11 13:21:55 2010
@@ -2,6 +2,33 @@
// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/struct2.c
// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
-// CHECK: struct2.c:13:11: error: external variable 'x1' declared with incompatible types in different translation units ('struct S1' vs. 'struct S1')
-// CHECK: struct1.c:16:11: note: declared here with type 'struct S1'
-// CHECK: 2 diagnostics
+// CHECK: struct1.c:13:8: warning: type 'struct S1' has incompatible definitions in different translation units
+// CHECK: struct1.c:15:7: note: field 'field2' has type 'int' here
+// CHECK: struct2.c:12:9: note: field 'field2' has type 'float' here
+// CHECK: struct2.c:15:11: error: external variable 'x1' declared with incompatible types in different translation units ('struct S1' vs. 'struct S1')
+// CHECK: struct1.c:18:11: note: declared here with type 'struct S1'
+// CHECK: struct1.c:21:8: warning: type 'struct S2' has incompatible definitions in different translation units
+// CHECK: struct2.c:18:7: note: 'S2' is a union here
+// CHECK: struct2.c:18:30: error: external variable 'x2' declared with incompatible types in different translation units ('union S2' vs. 'struct S2')
+// CHECK: struct1.c:21:31: note: declared here with type 'struct S2'
+// CHECK: struct1.c:24:8: warning: type 'struct S3' has incompatible definitions in different translation units
+// CHECK: struct1.c:24:36: note: field 'd' has type 'double' here
+// CHECK: struct2.c:21:8: note: no corresponding field here
+// CHECK: struct2.c:21:31: error: external variable 'x3' declared with incompatible types in different translation units ('struct S3' vs. 'struct S3')
+// CHECK: struct1.c:24:41: note: declared here with type 'struct S3'
+// CHECK: struct1.c:27:8: warning: type 'struct S4' has incompatible definitions in different translation units
+// CHECK: struct2.c:24:26: note: field 'f' has type 'float' here
+// CHECK: struct1.c:27:8: note: no corresponding field here
+// CHECK: struct2.c:24:31: error: external variable 'x4' declared with incompatible types in different translation units ('struct S4' vs. 'struct S4')
+// CHECK: struct1.c:27:22: note: declared here with type 'struct S4'
+// CHECK: struct1.c:33:8: warning: type 'struct S6' has incompatible definitions in different translation units
+// CHECK: struct1.c:33:33: note: bit-field 'j' with type 'unsigned int' and length 8 here
+// CHECK: struct2.c:30:33: note: field 'j' is not a bit-field
+// CHECK: struct2.c:30:38: error: external variable 'x6' declared with incompatible types in different translation units ('struct S6' vs. 'struct S6')
+// CHECK: struct1.c:33:42: note: declared here with type 'struct S6'
+// CHECK: struct1.c:36:8: warning: type 'struct S7' has incompatible definitions in different translation units
+// CHECK: struct1.c:36:33: note: bit-field 'j' with type 'unsigned int' and length 8 here
+// CHECK: struct2.c:33:33: note: bit-field 'j' with type 'unsigned int' and length 16 here
+// CHECK: struct2.c:33:43: error: external variable 'x7' declared with incompatible types in different translation units ('struct S7' vs. 'struct S7')
+// CHECK: struct1.c:36:42: note: declared here with type 'struct S7'
+// CHECK: 29 diagnostics
More information about the cfe-commits
mailing list