forked from OSchip/llvm-project
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:
parent
9be7200b08
commit
3996e249ed
|
@ -193,6 +193,9 @@ namespace clang {
|
||||||
/// \brief Retrieve the file manager that AST nodes are being imported from.
|
/// \brief Retrieve the file manager that AST nodes are being imported from.
|
||||||
FileManager &getFromFileManager() const { return FromFileManager; }
|
FileManager &getFromFileManager() const { return FromFileManager; }
|
||||||
|
|
||||||
|
/// \brief Retrieve the diagnostic formatter.
|
||||||
|
Diagnostic &getDiags() const { return Diags; }
|
||||||
|
|
||||||
/// \brief Report a diagnostic in the "to" context.
|
/// \brief Report a diagnostic in the "to" context.
|
||||||
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);
|
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);
|
||||||
|
|
||||||
|
|
|
@ -1193,7 +1193,8 @@ protected:
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
bool isSpelledAsLValue() const { return SpelledAsLValue; }
|
bool isSpelledAsLValue() const { return SpelledAsLValue; }
|
||||||
|
bool isInnerRef() const { return InnerRef; }
|
||||||
|
|
||||||
QualType getPointeeTypeAsWritten() const { return PointeeType; }
|
QualType getPointeeTypeAsWritten() const { return PointeeType; }
|
||||||
QualType getPointeeType() const {
|
QualType getPointeeType() const {
|
||||||
// FIXME: this might strip inner qualifiers; okay?
|
// FIXME: this might strip inner qualifiers; okay?
|
||||||
|
@ -2582,6 +2583,12 @@ public:
|
||||||
/// interface type, or 0 if there are none.
|
/// interface type, or 0 if there are none.
|
||||||
unsigned getNumProtocols() const { return NumProtocols; }
|
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)
|
/// qual_iterator and friends: this provides access to the (potentially empty)
|
||||||
/// list of protocols qualifying this interface.
|
/// list of protocols qualifying this interface.
|
||||||
typedef ObjCProtocolDecl* const * qual_iterator;
|
typedef ObjCProtocolDecl* const * qual_iterator;
|
||||||
|
@ -2683,6 +2690,12 @@ public:
|
||||||
/// interface type, or 0 if there are none.
|
/// interface type, or 0 if there are none.
|
||||||
unsigned getNumProtocols() const { return NumProtocols; }
|
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; }
|
bool isSugared() const { return false; }
|
||||||
QualType desugar() const { return QualType(this, 0); }
|
QualType desugar() const { return QualType(this, 0); }
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,10 +44,14 @@ struct S9 { int i; float f; } *x9;
|
||||||
// Incomplete type
|
// Incomplete type
|
||||||
struct S10 *x10;
|
struct S10 *x10;
|
||||||
|
|
||||||
// FIXME: Matches, but crashes the importer
|
// Matches
|
||||||
#if 0
|
|
||||||
struct ListNode {
|
struct ListNode {
|
||||||
int value;
|
int value;
|
||||||
struct ListNode *Next;
|
struct ListNode *Next;
|
||||||
} xList;
|
} xList;
|
||||||
#endif
|
|
||||||
|
// Mismatch due to struct used internally
|
||||||
|
struct DeepError {
|
||||||
|
int value;
|
||||||
|
struct DeeperError { int i; int f; } *Deeper;
|
||||||
|
} xDeep;
|
||||||
|
|
|
@ -46,3 +46,9 @@ struct ListNode {
|
||||||
int value;
|
int value;
|
||||||
struct ListNode *Next;
|
struct ListNode *Next;
|
||||||
} xList;
|
} xList;
|
||||||
|
|
||||||
|
// Mismatch due to struct used internally
|
||||||
|
struct DeepError {
|
||||||
|
int value;
|
||||||
|
struct DeeperError { int i; float f; } *Deeper;
|
||||||
|
} xDeep;
|
||||||
|
|
|
@ -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: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: 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: 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
|
||||||
|
|
Loading…
Reference in New Issue