diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-08-13 18:18:50 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-08-13 18:18:50 +0000 |
commit | 1c34fb78e7ebb9956c4282a5247a949869e6c09c (patch) | |
tree | e0bbcc06c58ed3c975834e73b00bb4b053f80f94 /clang/test | |
parent | c8d710cc82ee56cc59fb9b378b44623dcc53fd15 (diff) | |
download | bcm5719-llvm-1c34fb78e7ebb9956c4282a5247a949869e6c09c.tar.gz bcm5719-llvm-1c34fb78e7ebb9956c4282a5247a949869e6c09c.zip |
Fix implementation of C11 6.2.7/4 and C++11 [dcl.array]p3:
When a local extern declaration redeclares some other entity, the type of that
entity is merged with the prior type if the prior declaration is visible (in C)
or is declared in the same scope (in C++).
- Make LookupRedeclarationWithLinkage actually work in C++, use it in the right
set of cases, and make it track whether it found a shadowed declaration.
- Track whether we found a declaration in the same scope (for C++) including
across serialization and template instantiation.
llvm-svn: 188307
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CXX/basic/basic.link/p6.cpp | 53 | ||||
-rw-r--r-- | clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp | 152 | ||||
-rw-r--r-- | clang/test/PCH/cxx-templates.cpp | 16 | ||||
-rw-r--r-- | clang/test/PCH/cxx-templates.h | 15 | ||||
-rw-r--r-- | clang/test/Sema/extern-redecl.c | 24 | ||||
-rw-r--r-- | clang/test/SemaCXX/function-redecl.cpp | 21 |
6 files changed, 241 insertions, 40 deletions
diff --git a/clang/test/CXX/basic/basic.link/p6.cpp b/clang/test/CXX/basic/basic.link/p6.cpp index 8faec76fb3f..ac6dc2f1f1a 100644 --- a/clang/test/CXX/basic/basic.link/p6.cpp +++ b/clang/test/CXX/basic/basic.link/p6.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1y %s + +// expected-no-diagnostics // C++11 [basic.link]p6: // The name of a function declared in block scope and the name @@ -9,35 +11,34 @@ // block scope declaration declares that same entity and // receives the linkage of the previous declaration. -// rdar://13535367 -namespace test0 { - extern "C" int test0_array[]; - void declare() { extern int test0_array[100]; } - extern "C" int test0_array[]; - int value = sizeof(test0_array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} -} - -namespace test1 { - extern "C" int test1_array[]; - void test() { - { extern int test1_array[100]; } - extern int test1_array[]; - int x = sizeof(test1_array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} +extern int same_entity; +constexpr int *get1() { + int same_entity = 0; // not the same entity + { + extern int same_entity; + return &same_entity; } } +static_assert(get1() == &same_entity, "failed to find previous decl"); -namespace test2 { - void declare() { extern int test2_array[100]; } - extern int test2_array[]; - int value = sizeof(test2_array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} +static int same_entity_2[3]; +constexpr int *get2() { + // This is a redeclaration of the same entity, even though it doesn't + // inherit the type of the prior declaration. + extern int same_entity_2[]; + return same_entity_2; } +static_assert(get2() == same_entity_2, "failed to find previous decl"); -namespace test3 { - void test() { - { extern int test3_array[100]; } - extern int test3_array[]; - int x = sizeof(test3_array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} +static int different_entities; +constexpr int *get3() { + int different_entities = 0; + { + // FIXME: This is not a redeclaration of the prior entity, because + // it is not visible here. Under DR426, this is ill-formed, and without + // it, the static_assert below should fail. + extern int different_entities; + return &different_entities; } } - - +static_assert(get3() == &different_entities, "failed to find previous decl"); diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp new file mode 100644 index 00000000000..2dbc143065e --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p3.cpp @@ -0,0 +1,152 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1y -triple x86_64-linux-gnu %s + +// If there is a preceding declaration of the entity *in the same scope* in +// which the bound was specified, an omitted array bound is taken to be the +// same as in that earlier declaration + +// rdar://13535367 +namespace test0 { + extern "C" int array[]; + void declare() { extern int array[100]; } + int value1 = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} + extern "C" int array[]; + int value2 = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} +} + +namespace test1 { + extern "C" int array[]; + void test() { + { extern int array[100]; } + extern int array[]; + int x = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} + } +} + +namespace test2 { + void declare() { extern int array[100]; } + extern int array[]; + int value = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} +} + +namespace test3 { + void test() { + { extern int array[100]; } + extern int array[]; + int x = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} + } +} + +namespace test4 { + extern int array[]; + void test() { + extern int array[100]; + int x = sizeof(array); + } + int y = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} +} + +namespace test5 { + void test() { + extern int array[100]; + extern int array[]; + int x = sizeof(array); + } +} + +namespace test6 { + void test() { + extern int array[100]; + { + extern int array[]; + int x = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} + } + int y = sizeof(array); + } +} + +namespace test7 { + extern int array[100]; + void test() { + extern int array[]; + int x = sizeof(array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}} + } + int y = sizeof(array); +} + +namespace dependent { + template<typename T> void f() { + extern int arr1[]; + extern T arr1; + extern T arr2; + extern int arr2[]; + static_assert(sizeof(arr1) == 12, ""); + static_assert(sizeof(arr2) == 12, ""); + + // Use a failing test to ensure the type isn't considered dependent. + static_assert(sizeof(arr2) == 13, ""); // expected-error {{failed}} + } + + void g() { f<int[3]>(); } // expected-note {{in instantiation of}} + + template<typename T> void h1() { + extern T arr3; + { + int arr3; + { + extern int arr3[]; + // Detected in template definition. + (void)sizeof(arr3); // expected-error {{incomplete}} + } + } + } + + template<typename T> void h2() { + extern int arr4[3]; + { + int arr4; + { + extern T arr4; + // Detected in template instantiation. + (void)sizeof(arr4); // expected-error {{incomplete}} + } + } + } + + void i() { + h1<int[3]>(); + h2<int[]>(); // expected-note {{in instantiation of}} + } + + int arr5[3]; + template<typename T> void j() { + extern T arr5; + extern T arr6; + (void)sizeof(arr5); // expected-error {{incomplete}} + (void)sizeof(arr6); // expected-error {{incomplete}} + } + int arr6[3]; + + void k() { j<int[]>(); } // expected-note {{in instantiation of}} + + template<typename T, typename U> void l() { + extern T arrX; // expected-note {{previous}} + extern U arrX; // expected-error {{different type: 'int [4]' vs 'int [3]'}} + (void)sizeof(arrX); // expected-error {{incomplete}} + } + + void m() { + l<int[], int[3]>(); // ok + l<int[3], int[]>(); // ok + l<int[3], int[3]>(); // ok + l<int[3], int[4]>(); // expected-note {{in instantiation of}} + l<int[], int[]>(); // expected-note {{in instantiation of}} + } + + template<typename T> void n() { + extern T n_var; + } + template void n<int>(); + // FIXME: Diagnose this! + float n_var; + template void n<double>(); +} diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp index 763838b3bfa..e5ddd86e380 100644 --- a/clang/test/PCH/cxx-templates.cpp +++ b/clang/test/PCH/cxx-templates.cpp @@ -1,23 +1,21 @@ // Test this without pch. // RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h -verify %s -ast-dump -o - -// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h %s -emit-llvm -o - -DNO_ERRORS | FileCheck %s // Test with pch. // RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h // RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t -verify %s -ast-dump -o - -// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize -DNO_ERRORS | FileCheck %s // Test with modules. // RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -fmodules -x c++-header -emit-pch -o %t %S/cxx-templates.h // RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -fmodules -include-pch %t -verify %s -ast-dump -o - -// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -fmodules -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -fmodules -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize -DNO_ERRORS | FileCheck %s // Test with pch and delayed template parsing. // RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fdelayed-template-parsing -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h // RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fdelayed-template-parsing -fexceptions -include-pch %t -verify %s -ast-dump -o - -// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fdelayed-template-parsing -fexceptions -include-pch %t %s -emit-llvm -o - | FileCheck %s - -// expected-no-diagnostics +// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fdelayed-template-parsing -fexceptions -include-pch %t %s -emit-llvm -o - -DNO_ERRORS | FileCheck %s // CHECK: define weak_odr void @_ZN2S4IiE1mEv // CHECK: define linkonce_odr void @_ZN2S3IiE1mEv @@ -104,3 +102,9 @@ namespace cyclic_module_load { extern std::valarray<int> x; std::valarray<int> y(x); } + +#ifndef NO_ERRORS +// expected-error@cxx-templates.h:305 {{incomplete}} +template int local_extern::f<int[]>(); // expected-note {{in instantiation of}} +#endif +template int local_extern::g<int[]>(); diff --git a/clang/test/PCH/cxx-templates.h b/clang/test/PCH/cxx-templates.h index ce6b7051ecc..992f478e33e 100644 --- a/clang/test/PCH/cxx-templates.h +++ b/clang/test/PCH/cxx-templates.h @@ -296,3 +296,18 @@ namespace cyclic_module_load { }; } } + +namespace local_extern { + template<typename T> int f() { + extern int arr[3]; + { + extern T arr; + return sizeof(arr); + } + } + template<typename T> int g() { + extern int arr[3]; + extern T arr; + return sizeof(arr); + } +} diff --git a/clang/test/Sema/extern-redecl.c b/clang/test/Sema/extern-redecl.c index e9a4c571bd2..6bdb66e07f5 100644 --- a/clang/test/Sema/extern-redecl.c +++ b/clang/test/Sema/extern-redecl.c @@ -62,3 +62,27 @@ void test5c() { void *(*_malloc)() = &malloc; float *(*_calloc)() = &calloc; } + +void test6() { + extern int test6_array1[100]; + extern int test6_array2[100]; + void test6_fn1(int*); + void test6_fn2(int*); + { + // Types are only merged from visible declarations. + char test6_array2; + char test6_fn2; + { + extern int test6_array1[]; + extern int test6_array2[]; + (void)sizeof(test6_array1); // ok + (void)sizeof(test6_array2); // expected-error {{incomplete type}} + + void test6_fn1(); + void test6_fn2(); + test6_fn1(1.2); // expected-error {{passing 'double' to parameter of incompatible type 'int *'}} + // FIXME: This is valid, but we should warn on it. + test6_fn2(1.2); + } + } +} diff --git a/clang/test/SemaCXX/function-redecl.cpp b/clang/test/SemaCXX/function-redecl.cpp index b9d1f23af40..deb8e9d37fd 100644 --- a/clang/test/SemaCXX/function-redecl.cpp +++ b/clang/test/SemaCXX/function-redecl.cpp @@ -4,22 +4,27 @@ int foo(int); namespace N { void f1() { void foo(int); // okay + void bar(int); } - // FIXME: we shouldn't even need this declaration to detect errors - // below. - void foo(int); // expected-note{{previous declaration is here}} + void foo(int); // expected-note 2{{previous declaration is here}} void f2() { - int foo(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} + int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} + // FIXME: We should be able to diagnose the conflict between this + // declaration of 'bar' and the previous one, even though they come + // from different lexical scopes. + int bar(int); // expected-note {{previous declaration is here}} + int baz(int); // expected-note {{previous declaration is here}} { int foo; + int bar; + int baz; { - // FIXME: should diagnose this because it's incompatible with - // N::foo. However, name lookup isn't properly "skipping" the - // "int foo" above. - float foo(int); + float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} + float bar(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} + float baz(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} } } } |