diff options
author | Chris Lattner <sabre@nondot.org> | 2007-11-06 04:28:31 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-11-06 04:28:31 +0000 |
commit | fcc2d26e73192634dd05fb1b6800b5a063432feb (patch) | |
tree | 83e4d4a5bfae78d5280c43ce20c3ee65846fcf8e /Sema/SemaDecl.cpp | |
parent | c19b998b8bd4bda1a77a7bcf64226f9edfc01690 (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.cpp | 42 |
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; |