Reimplement the structural-equality checks used to determine whether

two types in different AST contexts are equivalent. Rather than
transforming the type from one context into the other context, we
perform a deep structural comparison of the types. This change
addresses a serious problem with recursive data types like

  struct ListNode {
    int value;
    struct ListNode *Next;
  } xList;

llvm-svn: 96278
This commit is contained in:
Douglas Gregor 2010-02-15 22:01:00 +00:00
parent 9be7200b08
commit 3996e249ed
6 changed files with 910 additions and 277 deletions

View File

@ -193,6 +193,9 @@ namespace clang {
/// \brief Retrieve the file manager that AST nodes are being imported from.
FileManager &getFromFileManager() const { return FromFileManager; }
/// \brief Retrieve the diagnostic formatter.
Diagnostic &getDiags() const { return Diags; }
/// \brief Report a diagnostic in the "to" context.
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);

View File

@ -1193,7 +1193,8 @@ protected:
}
public:
bool isSpelledAsLValue() const { return SpelledAsLValue; }
bool isInnerRef() const { return InnerRef; }
QualType getPointeeTypeAsWritten() const { return PointeeType; }
QualType getPointeeType() const {
// FIXME: this might strip inner qualifiers; okay?
@ -2582,6 +2583,12 @@ public:
/// interface type, or 0 if there are none.
unsigned getNumProtocols() const { return NumProtocols; }
/// \brief Retrieve the Ith protocol.
ObjCProtocolDecl *getProtocol(unsigned I) const {
assert(I < getNumProtocols() && "Out-of-range protocol access");
return qual_begin()[I];
}
/// qual_iterator and friends: this provides access to the (potentially empty)
/// list of protocols qualifying this interface.
typedef ObjCProtocolDecl* const * qual_iterator;
@ -2683,6 +2690,12 @@ public:
/// interface type, or 0 if there are none.
unsigned getNumProtocols() const { return NumProtocols; }
/// \brief Retrieve the Ith protocol.
ObjCProtocolDecl *getProtocol(unsigned I) const {
assert(I < getNumProtocols() && "Out-of-range protocol access");
return qual_begin()[I];
}
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }

File diff suppressed because it is too large Load Diff

View File

@ -44,10 +44,14 @@ struct S9 { int i; float f; } *x9;
// Incomplete type
struct S10 *x10;
// FIXME: Matches, but crashes the importer
#if 0
// Matches
struct ListNode {
int value;
struct ListNode *Next;
} xList;
#endif
// Mismatch due to struct used internally
struct DeepError {
int value;
struct DeeperError { int i; int f; } *Deeper;
} xDeep;

View File

@ -46,3 +46,9 @@ struct ListNode {
int value;
struct ListNode *Next;
} xList;
// Mismatch due to struct used internally
struct DeepError {
int value;
struct DeeperError { int i; float f; } *Deeper;
} xDeep;

View File

@ -31,4 +31,9 @@
// 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
// CHECK: struct1.c:56:10: warning: type 'struct DeeperError' has incompatible definitions in different translation units
// CHECK: struct1.c:56:35: note: field 'f' has type 'int' here
// CHECK: struct2.c:53:37: note: field 'f' has type 'float' here
// CHECK: struct2.c:54:3: error: external variable 'xDeep' declared with incompatible types in different translation units ('struct DeepError' vs. 'struct DeepError')
// CHECK: struct1.c:57:3: note: declared here with type 'struct DeepError'
// CHECK: 37 diagnostics