Skip to content

Commit 7d8072e

Browse files
committed
Diagnose the use of abstract types as array element types. Previously,
we were relying on checking for abstract class types when an array type was actually used to declare a variable, parameter, etc. However, we need to check when the construct the array for, e.g., SFINAE purposes (see DR337). Fixes problems with Boost's is_abstract type trait. llvm-svn: 102452
1 parent 9262f47 commit 7d8072e

File tree

3 files changed

+24
-15
lines changed

3 files changed

+24
-15
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ def err_allocation_of_abstract_type : Error<
406406
"allocation of an object of abstract type %0">;
407407
def err_throw_abstract_type : Error<
408408
"cannot throw an object of abstract type %0">;
409+
def err_array_of_abstract_type : Error<"array of abstract class type %0">;
409410

410411
def err_multiple_final_overriders : Error<
411412
"virtual function %q0 has more than one final overrider in %1">;

clang/lib/Sema/SemaType.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -607,15 +607,31 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
607607
SourceRange Brackets, DeclarationName Entity) {
608608

609609
SourceLocation Loc = Brackets.getBegin();
610-
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
611-
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
612-
// Not in C++, though. There we only dislike void.
613610
if (getLangOptions().CPlusPlus) {
611+
// C++ [dcl.array]p1:
612+
// T is called the array element type; this type shall not be a reference
613+
// type, the (possibly cv-qualified) type void, a function type or an
614+
// abstract class type.
615+
//
616+
// Note: function types are handled in the common path with C.
617+
if (T->isReferenceType()) {
618+
Diag(Loc, diag::err_illegal_decl_array_of_references)
619+
<< getPrintableNameForEntity(Entity) << T;
620+
return QualType();
621+
}
622+
614623
if (T->isVoidType()) {
615624
Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
616625
return QualType();
617626
}
627+
628+
if (RequireNonAbstractType(Brackets.getBegin(), T,
629+
diag::err_array_of_abstract_type))
630+
return QualType();
631+
618632
} else {
633+
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
634+
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
619635
if (RequireCompleteType(Loc, T,
620636
diag::err_illegal_decl_array_incomplete_type))
621637
return QualType();
@@ -627,13 +643,6 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
627643
return QualType();
628644
}
629645

630-
// C++ 8.3.2p4: There shall be no ... arrays of references ...
631-
if (T->isReferenceType()) {
632-
Diag(Loc, diag::err_illegal_decl_array_of_references)
633-
<< getPrintableNameForEntity(Entity) << T;
634-
return QualType();
635-
}
636-
637646
if (Context.getCanonicalType(T) == Context.UndeducedAutoTy) {
638647
Diag(Loc, diag::err_illegal_decl_array_of_auto)
639648
<< getPrintableNameForEntity(Entity);

clang/test/SemaCXX/abstract.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ void f() {
4242
t3(C()); // expected-error {{allocation of an object of abstract type 'C'}}
4343
}
4444

45-
C e1[2]; // expected-error {{variable type 'C' is an abstract class}}
46-
C (*e2)[2]; // expected-error {{variable type 'C' is an abstract class}}
47-
C (**e3)[2]; // expected-error {{variable type 'C' is an abstract class}}
45+
C e1[2]; // expected-error {{array of abstract class type 'C'}}
46+
C (*e2)[2]; // expected-error {{array of abstract class type 'C'}}
47+
C (**e3)[2]; // expected-error {{array of abstract class type 'C'}}
4848

49-
void t4(C c[2]); // expected-error {{parameter type 'C' is an abstract class}}
49+
void t4(C c[2]); // expected-error {{array of abstract class type 'C'}}
5050

5151
void t5(void (*)(C)); // expected-error {{parameter type 'C' is an abstract class}}
5252

@@ -168,4 +168,3 @@ namespace PureImplicit {
168168
struct D : C {};
169169
D y;
170170
}
171-

0 commit comments

Comments
 (0)