summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard@metafoo.co.uk>2019-12-16 18:26:19 -0800
committerRichard Smith <richard@metafoo.co.uk>2019-12-16 18:33:35 -0800
commiteea8ba097c4a86632b88291bea51eb710f8ae4fb (patch)
treee13d3795d4009530dad4bfae7228b6c327097f11
parentce12a523b0e1a64cea63ba099642d7f3492a3791 (diff)
downloadbcm5719-llvm-eea8ba097c4a86632b88291bea51eb710f8ae4fb.tar.gz
bcm5719-llvm-eea8ba097c4a86632b88291bea51eb710f8ae4fb.zip
Check whether the destination is a complete type in a static_cast (or
C-style cast) to an enumeration type. We previously forgot to check this, and happened to get away with it (with bad diagnostics) only because we misclassified incomplete enumeration types as not being unscoped enumeration types. This also fixes the misclassification.
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/lib/AST/Type.cpp6
-rw-r--r--clang/lib/Sema/SemaCast.cpp11
-rw-r--r--clang/test/SemaCXX/enum.cpp14
4 files changed, 14 insertions, 19 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 2529f7f7f72..3ffbbed1744 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6679,7 +6679,7 @@ def err_upcast_to_inaccessible_base : Error<
def err_bad_dynamic_cast_not_ref_or_ptr : Error<
"invalid target type %0 for dynamic_cast; target type must be a reference or pointer type to a defined class">;
def err_bad_dynamic_cast_not_class : Error<"%0 is not a class type">;
-def err_bad_dynamic_cast_incomplete : Error<"%0 is an incomplete type">;
+def err_bad_cast_incomplete : Error<"%0 is an incomplete type">;
def err_bad_dynamic_cast_not_ptr : Error<"cannot use dynamic_cast to convert from %0 to %1">;
def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">;
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 85447d682ba..c5ad711d872 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -1860,12 +1860,8 @@ bool Type::isIntegralOrUnscopedEnumerationType() const {
}
bool Type::isUnscopedEnumerationType() const {
- // Check for a complete enum type; incomplete enum types are not properly an
- // enumeration type in the sense required here.
- // C++0x: However, if the underlying type of the enum is fixed, it is
- // considered complete.
if (const auto *ET = dyn_cast<EnumType>(CanonicalType))
- return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
+ return !ET->getDecl()->isScoped();
return false;
}
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 741cf638760..d0b9fe12289 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -740,7 +740,7 @@ void CastOperation::CheckDynamicCast() {
assert(DestPointer && "Reference to void is not possible");
} else if (DestRecord) {
if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee,
- diag::err_bad_dynamic_cast_incomplete,
+ diag::err_bad_cast_incomplete,
DestRange)) {
SrcExpr = ExprError();
return;
@@ -785,7 +785,7 @@ void CastOperation::CheckDynamicCast() {
const RecordType *SrcRecord = SrcPointee->getAs<RecordType>();
if (SrcRecord) {
if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee,
- diag::err_bad_dynamic_cast_incomplete,
+ diag::err_bad_cast_incomplete,
SrcExpr.get())) {
SrcExpr = ExprError();
return;
@@ -1182,6 +1182,11 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
// The same goes for reverse floating point promotion/conversion and
// floating-integral conversions. Again, only floating->enum is relevant.
if (DestType->isEnumeralType()) {
+ if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
+ diag::err_bad_cast_incomplete)) {
+ SrcExpr = ExprError();
+ return TC_Failed;
+ }
if (SrcType->isIntegralOrEnumerationType()) {
Kind = CK_IntegralCast;
return TC_Success;
@@ -1651,7 +1656,7 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
CastKind &Kind, bool ListInitialization) {
if (DestType->isRecordType()) {
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
- diag::err_bad_dynamic_cast_incomplete) ||
+ diag::err_bad_cast_incomplete) ||
Self.RequireNonAbstractType(OpRange.getBegin(), DestType,
diag::err_allocation_of_abstract_type)) {
msg = 0;
diff --git a/clang/test/SemaCXX/enum.cpp b/clang/test/SemaCXX/enum.cpp
index 16ebebe31b6..b193a17ebf9 100644
--- a/clang/test/SemaCXX/enum.cpp
+++ b/clang/test/SemaCXX/enum.cpp
@@ -88,19 +88,13 @@ enum { }; // expected-warning{{declaration does not declare anything}}
typedef enum { }; // expected-warning{{typedef requires a name}}
// PR7921
-enum PR7921E {
- PR7921V = (PR7921E)(123)
-#if __cplusplus < 201103L
-// expected-error@-2 {{expression is not an integral constant expression}}
-#else
-// expected-error@-4 {{must have integral or unscoped enumeration type}}
-// FIXME: The above diagnostic isn't very good; we should instead complain about the type being incomplete.
-#endif
+enum PR7921E { // expected-note {{not complete until the closing '}'}}
+ PR7921V = (PR7921E)(123) // expected-error {{'PR7921E' is an incomplete type}}
};
void PR8089() {
- enum E; // expected-error{{ISO C++ forbids forward references to 'enum' types}}
- int a = (E)3; // expected-error{{cannot initialize a variable of type 'int' with an rvalue of type 'E'}}
+ enum E; // expected-error{{ISO C++ forbids forward references to 'enum' types}} expected-note {{forward declaration}}
+ int a = (E)3; // expected-error {{'E' is an incomplete type}}
}
// This is accepted as a GNU extension. In C++98, there was no provision for
OpenPOWER on IntegriCloud