aboutsummaryrefslogtreecommitdiff
path: root/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-11-06 04:28:31 +0000
committerChris Lattner <sabre@nondot.org>2007-11-06 04:28:31 +0000
commitfcc2d26e73192634dd05fb1b6800b5a063432feb (patch)
tree83e4d4a5bfae78d5280c43ce20c3ee65846fcf8e /Sema/SemaDecl.cpp
parentc19b998b8bd4bda1a77a7bcf64226f9edfc01690 (diff)
Add better validation for array types when merging decls. Patch
contributed by Oliver Hunt, thanks! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43750 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'Sema/SemaDecl.cpp')
-rw-r--r--Sema/SemaDecl.cpp42
1 files changed, 41 insertions, 1 deletions
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index 437ec30930..40414b46cd 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -254,6 +254,45 @@ FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, ScopedDecl *OldD) {
return New;
}
+
+/// hasUndefinedLength - Used by equivalentArrayTypes to determine whether the
+/// the outermost VariableArrayType has no size defined.
+static bool hasUndefinedLength(const ArrayType *Array) {
+ const VariableArrayType *VAT = Array->getAsVariableArrayType();
+ return VAT && !VAT->getSizeExpr();
+}
+
+/// equivalentArrayTypes - Used to determine whether two array types are
+/// equivalent.
+/// We need to check this explicitly as an incomplete array definition is
+/// considered a VariableArrayType, so will not match a complete array
+/// definition that would be otherwise equivalent.
+static bool areEquivalentArrayTypes(QualType NewQType, QualType OldQType) {
+ const ArrayType *NewAT = NewQType->getAsArrayType();
+ const ArrayType *OldAT = OldQType->getAsArrayType();
+
+ if (!NewAT || !OldAT)
+ return false;
+
+ // If either (or both) array types in incomplete we need to strip off the
+ // outer VariableArrayType. Once the outer VAT is removed the remaining
+ // types must be identical if the array types are to be considered
+ // equivalent.
+ // eg. int[][1] and int[1][1] become
+ // VAT(null, CAT(1, int)) and CAT(1, CAT(1, int))
+ // removing the outermost VAT gives
+ // CAT(1, int) and CAT(1, int)
+ // which are equal, therefore the array types are equivalent.
+ if (hasUndefinedLength(NewAT) || hasUndefinedLength(OldAT)) {
+ if (NewAT->getIndexTypeQualifier() != OldAT->getIndexTypeQualifier())
+ return false;
+ NewQType = NewAT->getElementType();
+ OldQType = OldAT->getElementType();
+ }
+
+ return NewQType == OldQType;
+}
+
/// MergeVarDecl - We just parsed a variable 'New' which has the same name
/// and scope as a previous declaration 'Old'. Figure out how to resolve this
/// situation, merging decls or emitting diagnostics as appropriate.
@@ -282,7 +321,8 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, ScopedDecl *OldD) {
OldIsTentative = true;
}
// Verify the types match.
- if (Old->getCanonicalType() != New->getCanonicalType()) {
+ if (Old->getCanonicalType() != New->getCanonicalType() &&
+ !areEquivalentArrayTypes(New->getCanonicalType(), Old->getCanonicalType())) {
Diag(New->getLocation(), diag::err_redefinition, New->getName());
Diag(Old->getLocation(), diag::err_previous_definition);
return New;