[clang] eea8ba0 - Check whether the destination is a complete type in a static_cast (or

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 16 18:33:49 PST 2019


Author: Richard Smith
Date: 2019-12-16T18:33:35-08:00
New Revision: eea8ba097c4a86632b88291bea51eb710f8ae4fb

URL: https://github.com/llvm/llvm-project/commit/eea8ba097c4a86632b88291bea51eb710f8ae4fb
DIFF: https://github.com/llvm/llvm-project/commit/eea8ba097c4a86632b88291bea51eb710f8ae4fb.diff

LOG: 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.

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/AST/Type.cpp
    clang/lib/Sema/SemaCast.cpp
    clang/test/SemaCXX/enum.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 2529f7f7f727..3ffbbed17444 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 85447d682ba2..c5ad711d872e 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 741cf6387606..d0b9fe122895 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 16ebebe31b6d..b193a17ebf9e 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 at -2 {{expression is not an integral constant expression}}
-#else
-// expected-error at -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


        


More information about the cfe-commits mailing list