From: Yaron Keren Date: Fri, 22 Jan 2016 19:03:27 +0000 (+0000) Subject: Merge templated static member variables, fixes http://llvm.org/pr26179. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ea5b0ddd89b0b681d410714cbcd20fcd713dcf05;p=clang Merge templated static member variables, fixes http://llvm.org/pr26179. Patch by Vassil Vassilev! Reviewed by Richard Smith. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@258524 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 5bf95f878d..9bcd9a0164 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -2595,8 +2595,24 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { // Variables with the same type and linkage match. if (VarDecl *VarX = dyn_cast(X)) { VarDecl *VarY = cast(Y); - return (VarX->getLinkageInternal() == VarY->getLinkageInternal()) && - VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType()); + if (VarX->getLinkageInternal() == VarY->getLinkageInternal()) { + ASTContext &C = VarX->getASTContext(); + if (C.hasSameType(VarX->getType(), VarY->getType())) + return true; + + // We can get decls with different types on the redecl chain. Eg. + // template struct S { static T Var[]; }; // #1 + // template T S::Var[sizeof(T)]; // #2 + // Only? happens when completing an incomplete array type. In this case + // when comparing #1 and #2 we should go through their elements types. + const ArrayType *VarXTy = C.getAsArrayType(VarX->getType()); + const ArrayType *VarYTy = C.getAsArrayType(VarY->getType()); + if (!VarXTy || !VarYTy) + return false; + if (VarXTy->isIncompleteArrayType() || VarYTy->isIncompleteArrayType()) + return C.hasSameType(VarXTy->getElementType(), VarYTy->getElementType()); + } + return false; } // Namespaces with the same name and inlinedness match. diff --git a/test/Modules/Inputs/PR26179/A.h b/test/Modules/Inputs/PR26179/A.h new file mode 100644 index 0000000000..ce95fafb4b --- /dev/null +++ b/test/Modules/Inputs/PR26179/A.h @@ -0,0 +1,4 @@ +#include "basic_string.h" +#include "B.h" + +int *p = a; diff --git a/test/Modules/Inputs/PR26179/B.h b/test/Modules/Inputs/PR26179/B.h new file mode 100644 index 0000000000..eb8d1c29e7 --- /dev/null +++ b/test/Modules/Inputs/PR26179/B.h @@ -0,0 +1,2 @@ +#include "basic_string.h" +extern int a[5]; diff --git a/test/Modules/Inputs/PR26179/basic_string.h b/test/Modules/Inputs/PR26179/basic_string.h new file mode 100644 index 0000000000..afd1e0d3b3 --- /dev/null +++ b/test/Modules/Inputs/PR26179/basic_string.h @@ -0,0 +1,14 @@ +#ifndef _GLIBCXX_STRING +#define _GLIBCXX_STRING 1 + +template +struct basic_string { + static T _S_empty_rep_storage[]; +}; + +template +T basic_string::_S_empty_rep_storage[sizeof(T)]; + +extern int a[]; + +#endif diff --git a/test/Modules/Inputs/PR26179/module.modulemap b/test/Modules/Inputs/PR26179/module.modulemap new file mode 100644 index 0000000000..49374181d7 --- /dev/null +++ b/test/Modules/Inputs/PR26179/module.modulemap @@ -0,0 +1,9 @@ +module A { + header "A.h" + export * +} + +module B { + header "B.h" + export * +} diff --git a/test/Modules/pr26179.cpp b/test/Modules/pr26179.cpp new file mode 100644 index 0000000000..f25f1ce24b --- /dev/null +++ b/test/Modules/pr26179.cpp @@ -0,0 +1,7 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -I%S/Inputs/PR26179 -verify %s +// RUN: %clang_cc1 -fmodules -fmodule-map-file=%S/Inputs/PR26179/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR26179 -verify %s + +#include "A.h" + +// expected-no-diagnostics